{"action":"created","comment":{"url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/comments/221155246","pull_request_review_id":159735984,"id":221155246,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyMTE1NTI0Ng==","diff_hunk":"@@ -1,41 +1,79 @@\n import KJUR from 'jsrsasign';\n-\n-function capitalizePrefix(prefix) {\n-    return prefix.charAt(0).toUpperCase() + prefix.substring(1);\n-}\n+import qs from 'querystring';\n \n function testService($http, UtilityService) {\n     return {\n         /**\n-         * APEX Base string generation\n+         * Formulate Apex Signature base string\n          *\n-         * @param params.request and params.uri always required, used to generate the beginning of the base string.\n-         * params.request: HTTP Method: GET, POST etc\n-         * params.uri: Signature URL - ${protocol}//${hostname}${pathname} (query strings need to be stripped)\n-         * @param params.realm Unused.\n-         * @param params.prefix Prefix added to other param keys, see below\n-         * @param params Required params (below) and query string params\n-         * The following are appended to params.prefix:\n-         * params.app_id: App ID\n-         * params.nonce: Nonce.\n-         * params.signature_method: HMACSHA256 or SHA256withRSA\n-         * params.timestamp: Unix timestamp\n-         * params.version: Version number, 1.0 by default\n+         * @param {object} basestringOptions Base string formulation request properties in JSON object\n+         * @param {string} basestringOptions.signatureUrl API signature URL\n+         * @param {string} basestringOptions.authPrefix Apex auth prefix\n+         * @param {string} basestringOptions.signatureMethod If L1 auth, HMACSHA256; if L2 auth, SHA256withRSA\n+         * @param {string} basestringOptions.appId Apex app ID\n+         * @param {string} basestringOptions.httpMethod HTTP Verb\n+         * @param {string} basestringOptions.appVersion Apex app version\n+         * @param {number} basestringOptions.nonce A nonce. Use once only\n+         * @param {number} basestringOptions.timestamp Unix timestamp (ms)\n+         * @param {object} [basestringOptions.queryString] Query string in API\n+         * @param {object} [basestringOptions.formData] HTTP POST or PUT body in x-www-form-urlencoded format\n          *\n-         * The above params are then sorted before being used to construct the base string.\n-         *\n-         * @returns {string} Base string in the format: ${httpMethod}&${signatureUrl}&${sortedKeyValuePairs}\n+         * @returns {string} sigBaseString Signature base string for signing\n+         * @public\n          */\n-        generateBasestring(params) {\n-            let sortedParams = UtilityService.sortJSON(params);\n-            let sortedKeys = Object.keys(sortedParams);\n-            let baseString = sortedParams.request.toUpperCase() + '&' + sortedParams.uri;\n-            for (let key of sortedKeys) {\n-                if (!['request', 'uri', 'realm', 'prefix'].includes(key)) {\n-                    baseString += '&' + key + '=' + sortedParams[key];\n-                }\n+        generateBasestring(basestringOptions) {\n+            const signatureUrl = new URL(basestringOptions.signatureUrl);\n+\n+            if (signatureUrl.protocol !== 'http:' && signatureUrl.protocol !== 'https:') {\n+                throw new Error('Only http and https protocols are supported');\n+            }\n+\n+            // Remove port from url\n+            delete signatureUrl.port;\n+            let basestringUrl = signatureUrl.origin + signatureUrl.pathname;\n+\n+            let defaultParams = {};\n+\n+            let prefixedAppId = basestringOptions.authPrefix.toLowerCase() + '_app_id';\n+            let prefixedNonce = basestringOptions.authPrefix.toLowerCase() + '_nonce';\n+            let prefixedSignatureMethod = basestringOptions.authPrefix.toLowerCase() + '_signature_method';\n+            let prefixedTimestamp = basestringOptions.authPrefix.toLowerCase() + '_timestamp';\n+            let prefixedVersion = basestringOptions.authPrefix.toLowerCase() + '_version';\n+\n+            defaultParams[prefixedAppId] = basestringOptions.appId;\n+            defaultParams[prefixedNonce] = basestringOptions.nonce;\n+            defaultParams[prefixedSignatureMethod] = basestringOptions.signatureMethod;\n+            defaultParams[prefixedTimestamp] = basestringOptions.timestamp;\n+            defaultParams[prefixedVersion] = basestringOptions.appVersion;\n+\n+            // Add support to handle array in QueryString and name collision between queryString and formData\n+            let paramsArray = parseParams(defaultParams);\n+\n+            // Found query string in url, transfer to params property\n+            if (signatureUrl.search != null && signatureUrl.search.length > 0) {\n+                let params = qs.parse(signatureUrl.search.slice(1));\n+                paramsArray = paramsArray.concat(parseParams(params));\n+            }\n+\n+            if (basestringOptions.queryString != null) {","path":"src/service/testService.js","position":86,"original_position":86,"commit_id":"6a29776e6e6166276345e211a7bd7addeb649c04","original_commit_id":"6a29776e6e6166276345e211a7bd7addeb649c04","user":{"login":"robincher","id":328109,"node_id":"MDQ6VXNlcjMyODEwOQ==","avatar_url":"https://avatars2.githubusercontent.com/u/328109?v=4","gravatar_id":"","url":"https://api.github.com/users/robincher","html_url":"https://github.com/robincher","followers_url":"https://api.github.com/users/robincher/followers","following_url":"https://api.github.com/users/robincher/following{/other_user}","gists_url":"https://api.github.com/users/robincher/gists{/gist_id}","starred_url":"https://api.github.com/users/robincher/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robincher/subscriptions","organizations_url":"https://api.github.com/users/robincher/orgs","repos_url":"https://api.github.com/users/robincher/repos","events_url":"https://api.github.com/users/robincher/events{/privacy}","received_events_url":"https://api.github.com/users/robincher/received_events","type":"User","site_admin":false},"body":"Just a random comment, will we have a condition if both queryString and formData defined? This could be an additional validation we do in the main node js library","created_at":"2018-09-28T06:47:07Z","updated_at":"2018-09-28T06:47:07Z","html_url":"https://github.com/GovTechSG/apex-signature-validator/pull/11#discussion_r221155246","pull_request_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/comments/221155246"},"html":{"href":"https://github.com/GovTechSG/apex-signature-validator/pull/11#discussion_r221155246"},"pull_request":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11"}}},"pull_request":{"url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11","id":218844390,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE4ODQ0Mzkw","html_url":"https://github.com/GovTechSG/apex-signature-validator/pull/11","diff_url":"https://github.com/GovTechSG/apex-signature-validator/pull/11.diff","patch_url":"https://github.com/GovTechSG/apex-signature-validator/pull/11.patch","issue_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/11","number":11,"state":"open","locked":false,"title":"Redesign and rewrite","user":{"login":"weijunyu","id":8362958,"node_id":"MDQ6VXNlcjgzNjI5NTg=","avatar_url":"https://avatars3.githubusercontent.com/u/8362958?v=4","gravatar_id":"","url":"https://api.github.com/users/weijunyu","html_url":"https://github.com/weijunyu","followers_url":"https://api.github.com/users/weijunyu/followers","following_url":"https://api.github.com/users/weijunyu/following{/other_user}","gists_url":"https://api.github.com/users/weijunyu/gists{/gist_id}","starred_url":"https://api.github.com/users/weijunyu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weijunyu/subscriptions","organizations_url":"https://api.github.com/users/weijunyu/orgs","repos_url":"https://api.github.com/users/weijunyu/repos","events_url":"https://api.github.com/users/weijunyu/events{/privacy}","received_events_url":"https://api.github.com/users/weijunyu/received_events","type":"User","site_admin":false},"body":"# Description\r\n\r\nSignature validator rewritten. \r\n- Users now enter API URL directly. This allows them to call any URL they choose.\r\n- If api.gov.sg API is used, .i and .e subdomains are automatically added and displayed\r\n- Implementation for generating base strings and signatures are now in line with node-apex-security\r\n- Flow and UI redesigned\r\n- Rewrite of signature validator and testservice. All redundant code removed\r\n\r\n## How Has This Been Tested?\r\n\r\nManually\r\n","created_at":"2018-09-28T03:30:33Z","updated_at":"2018-09-28T06:47:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"343f2c6f1f2540b3d6a9aa216756c6f131ee25f0","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11/commits","review_comments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11/comments","review_comment_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/11/comments","statuses_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/statuses/6a29776e6e6166276345e211a7bd7addeb649c04","head":{"label":"GovTechSG:development","ref":"development","sha":"6a29776e6e6166276345e211a7bd7addeb649c04","user":{"login":"GovTechSG","id":12439141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNDM5MTQx","avatar_url":"https://avatars0.githubusercontent.com/u/12439141?v=4","gravatar_id":"","url":"https://api.github.com/users/GovTechSG","html_url":"https://github.com/GovTechSG","followers_url":"https://api.github.com/users/GovTechSG/followers","following_url":"https://api.github.com/users/GovTechSG/following{/other_user}","gists_url":"https://api.github.com/users/GovTechSG/gists{/gist_id}","starred_url":"https://api.github.com/users/GovTechSG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GovTechSG/subscriptions","organizations_url":"https://api.github.com/users/GovTechSG/orgs","repos_url":"https://api.github.com/users/GovTechSG/repos","events_url":"https://api.github.com/users/GovTechSG/events{/privacy}","received_events_url":"https://api.github.com/users/GovTechSG/received_events","type":"Organization","site_admin":false},"repo":{"id":120737014,"node_id":"MDEwOlJlcG9zaXRvcnkxMjA3MzcwMTQ=","name":"apex-signature-validator","full_name":"GovTechSG/apex-signature-validator","private":false,"owner":{"login":"GovTechSG","id":12439141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNDM5MTQx","avatar_url":"https://avatars0.githubusercontent.com/u/12439141?v=4","gravatar_id":"","url":"https://api.github.com/users/GovTechSG","html_url":"https://github.com/GovTechSG","followers_url":"https://api.github.com/users/GovTechSG/followers","following_url":"https://api.github.com/users/GovTechSG/following{/other_user}","gists_url":"https://api.github.com/users/GovTechSG/gists{/gist_id}","starred_url":"https://api.github.com/users/GovTechSG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GovTechSG/subscriptions","organizations_url":"https://api.github.com/users/GovTechSG/orgs","repos_url":"https://api.github.com/users/GovTechSG/repos","events_url":"https://api.github.com/users/GovTechSG/events{/privacy}","received_events_url":"https://api.github.com/users/GovTechSG/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/GovTechSG/apex-signature-validator","description":"HTTP Signature validator and test client for APEX ","fork":false,"url":"https://api.github.com/repos/GovTechSG/apex-signature-validator","forks_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/forks","keys_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/teams","hooks_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/hooks","issue_events_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/events{/number}","events_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/events","assignees_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/assignees{/user}","branches_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/branches{/branch}","tags_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/tags","blobs_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/refs{/sha}","trees_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/statuses/{sha}","languages_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/languages","stargazers_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/stargazers","contributors_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/contributors","subscribers_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/subscribers","subscription_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/subscription","commits_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/commits{/sha}","git_commits_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/commits{/sha}","comments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/comments{/number}","issue_comment_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/comments{/number}","contents_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/contents/{+path}","compare_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/merges","archive_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/downloads","issues_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues{/number}","pulls_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls{/number}","milestones_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/milestones{/number}","notifications_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/labels{/name}","releases_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/releases{/id}","deployments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/deployments","created_at":"2018-02-08T09:03:13Z","updated_at":"2018-07-19T15:27:37Z","pushed_at":"2018-09-28T06:22:14Z","git_url":"git://github.com/GovTechSG/apex-signature-validator.git","ssh_url":"git@github.com:GovTechSG/apex-signature-validator.git","clone_url":"https://github.com/GovTechSG/apex-signature-validator.git","svn_url":"https://github.com/GovTechSG/apex-signature-validator","homepage":"https://govtechsg.github.io/apex-signature-validator/","size":3958,"stargazers_count":2,"watchers_count":2,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":1,"open_issues":1,"watchers":2,"default_branch":"master"}},"base":{"label":"GovTechSG:master","ref":"master","sha":"a4cc415e72a8670bf34800ec6c57d1da2630a1e3","user":{"login":"GovTechSG","id":12439141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNDM5MTQx","avatar_url":"https://avatars0.githubusercontent.com/u/12439141?v=4","gravatar_id":"","url":"https://api.github.com/users/GovTechSG","html_url":"https://github.com/GovTechSG","followers_url":"https://api.github.com/users/GovTechSG/followers","following_url":"https://api.github.com/users/GovTechSG/following{/other_user}","gists_url":"https://api.github.com/users/GovTechSG/gists{/gist_id}","starred_url":"https://api.github.com/users/GovTechSG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GovTechSG/subscriptions","organizations_url":"https://api.github.com/users/GovTechSG/orgs","repos_url":"https://api.github.com/users/GovTechSG/repos","events_url":"https://api.github.com/users/GovTechSG/events{/privacy}","received_events_url":"https://api.github.com/users/GovTechSG/received_events","type":"Organization","site_admin":false},"repo":{"id":120737014,"node_id":"MDEwOlJlcG9zaXRvcnkxMjA3MzcwMTQ=","name":"apex-signature-validator","full_name":"GovTechSG/apex-signature-validator","private":false,"owner":{"login":"GovTechSG","id":12439141,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEyNDM5MTQx","avatar_url":"https://avatars0.githubusercontent.com/u/12439141?v=4","gravatar_id":"","url":"https://api.github.com/users/GovTechSG","html_url":"https://github.com/GovTechSG","followers_url":"https://api.github.com/users/GovTechSG/followers","following_url":"https://api.github.com/users/GovTechSG/following{/other_user}","gists_url":"https://api.github.com/users/GovTechSG/gists{/gist_id}","starred_url":"https://api.github.com/users/GovTechSG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GovTechSG/subscriptions","organizations_url":"https://api.github.com/users/GovTechSG/orgs","repos_url":"https://api.github.com/users/GovTechSG/repos","events_url":"https://api.github.com/users/GovTechSG/events{/privacy}","received_events_url":"https://api.github.com/users/GovTechSG/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/GovTechSG/apex-signature-validator","description":"HTTP Signature validator and test client for APEX ","fork":false,"url":"https://api.github.com/repos/GovTechSG/apex-signature-validator","forks_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/forks","keys_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/teams","hooks_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/hooks","issue_events_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/events{/number}","events_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/events","assignees_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/assignees{/user}","branches_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/branches{/branch}","tags_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/tags","blobs_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/refs{/sha}","trees_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/statuses/{sha}","languages_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/languages","stargazers_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/stargazers","contributors_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/contributors","subscribers_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/subscribers","subscription_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/subscription","commits_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/commits{/sha}","git_commits_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/git/commits{/sha}","comments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/comments{/number}","issue_comment_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/comments{/number}","contents_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/contents/{+path}","compare_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/merges","archive_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/downloads","issues_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues{/number}","pulls_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls{/number}","milestones_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/milestones{/number}","notifications_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/labels{/name}","releases_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/releases{/id}","deployments_url":"https://api.github.com/repos/GovTechSG/apex-signature-validator/deployments","created_at":"2018-02-08T09:03:13Z","updated_at":"2018-07-19T15:27:37Z","pushed_at":"2018-09-28T06:22:14Z","git_url":"git://github.com/GovTechSG/apex-signature-validator.git","ssh_url":"git@github.com:GovTechSG/apex-signature-validator.git","clone_url":"https://github.com/GovTechSG/apex-signature-validator.git","svn_url":"https://github.com/GovTechSG/apex-signature-validator","homepage":"https://govtechsg.github.io/apex-signature-validator/","size":3958,"stargazers_count":2,"watchers_count":2,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":1,"open_issues":1,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11"},"html":{"href":"https://github.com/GovTechSG/apex-signature-validator/pull/11"},"issue":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/11"},"comments":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/issues/11/comments"},"review_comments":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11/comments"},"review_comment":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/pulls/11/commits"},"statuses":{"href":"https://api.github.com/repos/GovTechSG/apex-signature-validator/statuses/6a29776e6e6166276345e211a7bd7addeb649c04"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"robincher"}}