diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..0f37dfc
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,80 @@
+version: 2
+defaults: &defaults
+    docker:
+      - image: circleci/python:2.7-stretch-browsers
+install_dependency: &install_dependency
+  name: Installation of build and deployment dependencies.
+  command: |
+    sudo apt install jq
+    sudo pip install awscli --upgrade
+    sudo pip install docker-compose
+install_deploysuite: &install_deploysuite
+  name: Installation of install_deploysuite.
+  command: |
+    git clone --branch v1.4 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript
+    cp ./../buildscript/master_deploy.sh .
+    cp ./../buildscript/buildenv.sh .
+    cp ./../buildscript/awsconfiguration.sh .
+restore_cache_settings_for_build: &restore_cache_settings_for_build
+  key: docker-node-modules-{{ checksum "package-lock.json" }}
+
+save_cache_settings: &save_cache_settings
+  key: docker-node-modules-{{ checksum "package-lock.json" }}
+  paths:
+    - node_modules
+
+builddeploy_steps: &builddeploy_steps
+      - checkout
+      - setup_remote_docker
+      - run: *install_dependency
+      - run: *install_deploysuite
+      # - restore_cache: *restore_cache_settings_for_build
+      - run: ./build.sh ${APPNAME}
+      # - save_cache: *save_cache_settings
+      - deploy:
+          name: Running MasterScript.
+          command: |
+            ./awsconfiguration.sh $DEPLOY_ENV
+            source awsenvconf
+            ./buildenv.sh -e $DEPLOY_ENV -b ${LOGICAL_ENV}-${APPNAME}-deployvar
+            source buildenvvar
+            ./master_deploy.sh -d ECS -e $DEPLOY_ENV -t latest -s ${LOGICAL_ENV}-global-appvar,${LOGICAL_ENV}-${APPNAME}-appvar -i ${APPNAME}
+
+
+jobs:
+  # Build & Deploy against development backend
+  "build-dev":
+    <<: *defaults
+    environment:
+      DEPLOY_ENV: "DEV"
+      LOGICAL_ENV: "dev"
+      APPNAME: "or-review-processor"    
+    steps: *builddeploy_steps
+
+  "build-prod":
+    <<: *defaults
+    environment:
+      DEPLOY_ENV: "PROD"
+      LOGICAL_ENV: "prod"    
+      APPNAME: "or-review-processor"  
+    steps: *builddeploy_steps
+
+workflows:
+  version: 2
+  build:
+    jobs:
+      # Development builds are executed on "develop" branch only.
+      - "build-dev":
+          context : org-global
+          filters:
+            branches:
+              only:
+                - develop
+
+      # Production builds are exectuted only on tagged commits to the
+      # master branch.
+      - "build-prod":
+          context : org-global
+          filters:
+            branches:
+              only: master
diff --git a/README.md b/README.md
index 89ac5c2..7d15138 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-# Topcoder - OR Review Processor
+# Topcoder - Scorecard Processor
+
 
 ## Dependencies
 
@@ -7,7 +8,7 @@
 
 ## Configuration
 
-Configuration for the OR review processor is at `config/default.js`.
+Configuration for the Scorecard processor is at `config/default.js`.
 The following parameters can be set in config files or in env variables:
 - LOG_LEVEL: the log level; default value: 'debug'
 - KAFKA_URL: comma separated Kafka hosts; default value: 'localhost:9092'
@@ -17,11 +18,13 @@ The following parameters can be set in config files or in env variables:
 - KAFKA_CLIENT_CERT_KEY: Kafka connection private key, optional; default value is undefined;
     if not provided, then SSL connection is not used, direct insecure connection is used;
     if provided, it can be either path to private key file or private key content
-- KAFKA_GROUP_ID: consumer group id; default value: 'or-review-processor'
-- OR_REVIEW_TOPIC : OR review processor topic, default value is 'or.notification.create'
-- REVIEW_API_URL: review api url, default is 'https://api.topcoder-dev.com/v5/reviews'
-- SUBMISSION_API_URL: submission api url, default is 'https://api.topcoder-dev.com/v5/submissions'
-- REVIEW_TYPE_API_URL: review type api url, default is 'https://api.topcoder-dev.com/v5/reviewTypes'
+- KAFKA_GROUP_ID: consumer group id; default value: 'scorecard-processor'
+- REVIEW_TOPIC : Review topic, default value is 'submission.notification.score'
+- AGGREGATE_SUBMISSION_TOPIC : aggregate submission topic, default value is 'submission.notification.aggregate'
+- SUBMISSION_API_URL: submission api url, default is 'https://api.topcoder-dev.com/v5'
+- CHALLENGE_API_URL: challenge API URL, default is 'https://api.topcoder-dev.com/v4/challenges'
+- SCORECARD_API_URL: scorecard API URL, default is 'http://localhost:4000/scorecards'
+- BUS_API_URL: bus API URL, default is 'https://api.topcoder-dev.com/v5/bus/events'
 - AUTH0_URL: Auth0 URL, used to get TC M2M token
 - AUTH0_AUDIENCE: Auth0 audience, used to get TC M2M token
 - TOKEN_CACHE_TIME: Auth0 token cache time, used to get TC M2M token
@@ -33,8 +36,8 @@ The following parameters can be set in config files or in env variables:
 Also note that there is a `/health` endpoint that checks for the health of the app. This sets up an expressjs server and listens on the environment variable `PORT`. It's not part of the configuration file and needs to be passed as an environment variable
 
 Configuration for the tests is at `config/test.js`, only add such new configurations different from `config/default.js`
-- WAIT_TIME: wait time used in test, default is 1000 or one second
-- REVIEW_SUMMATION_API_URL: review summation api url, used to clear resource during testing, default is 'https://api.topcoder-dev.com/v5/reviewSummations'
+- WAIT_TIME: wait time used in test, default is 2000 or 2 seconds
+- SCORECARD_API_URL: the scorecard api url used in testing
 
 ## Local Kafka setup
 
@@ -49,16 +52,19 @@ Configuration for the tests is at `config/test.js`, only add such new configurat
   `bin/kafka-server-start.sh config/server.properties`
 - note that the zookeeper server is at localhost:2181, and Kafka server is at localhost:9092
 - use another terminal, go to same directory, create the needed topics:
-  `bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic or.notification.create`
+  `bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic submission.notification.score`
+  `bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic submission.notification.aggregate`
+  `bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic avscan.action.scan`
+  `bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic or.action.review`
 - verify that the topics are created:
   `bin/kafka-topics.sh --list --zookeeper localhost:2181`,
   it should list out the created topics
-- run the producer and then write some message into the console to send to the `or.notification.create` topic:
-  `bin/kafka-console-producer.sh --broker-list localhost:9092 --topic or.notification.create`
+- run the producer and then write some message into the console to send to the `submission.notification.score` topic:
+  `bin/kafka-console-producer.sh --broker-list localhost:9092 --topic submission.notification.score`
   in the console, write message, one message per line:
-  `{ "topic": "or.notification.create", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 90, "submissionId": 206743, "reviewId": 390087, "scorecardId": 300001610, "reviewerId": 151743, "reviewTypeId": 2, "eventType": "CREATE" } }`
+  `{ "topic": "submission.notification.score", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 85, "submissionId": 206744, "reviewId": 390088, "scorecardId": 300001610, "reviewerId": 151743, "reviewTypeId": 2, "eventType": "CREATE" } }`
 - optionally, use another terminal, go to same directory, start a consumer to view the messages:
-  `bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic or.notification.create --from-beginning`
+  `bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic submission.notification.score --from-beginning`
 - writing/reading messages to/from other topics are similar
 
 ## Local deployment
@@ -78,9 +84,17 @@ npm run lint:fix # To fix possible lint errors
 npm start
 ```
 
+
 ## Testing
 - Run `npm run test` to execute unit tests.
 - RUN `npm run e2e` to execute e2e tests.
 
 ## Verification
 Refer to the verification document `Verification.md`
+
+## Notes
+- the retrieved M2M token has no permission to delete review summation,
+  but clearing review summation is not necessary, so we may ignore such forbidden error
+- usually, we should use TC bus API (POST /v5/bus/events) to send new messages for SubmissionProcessorService.processSubmission,
+  but recently some TC dev API is not available, and the bus API fails with `504 temporarily unavailable error` when
+  posting to topic `or.action.review`, so instead, this processor uses a Kafka producer to send new messages
diff --git a/Verification.md b/Verification.md
index d62aa74..095ff8b 100644
--- a/Verification.md
+++ b/Verification.md
@@ -1,60 +1,146 @@
-# Topcoder - OR Review Processor
-
-## Verification
-
-1. start kafka server, start processor app
-2. start kafka-console-producer to write messages to `or.notification.create` topic:
-  `bin/kafka-console-producer.sh --broker-list localhost:9092 --topic or.notification.create`
-3. write message:
-  `{ "topic": "or.notification.create", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 85, "submissionId": 206744, "reviewId": 390088, "scorecardId": 300001610, "reviewerId": 151743, "reviewTypeId": 2, "eventType": "CREATE" } }`
-4. watch the app console, it should show info of processing the message
-5. Use Postman to verify the data has been updated in remote server
-  GET https://api.topcoder-dev.com/v5/submissions?legacySubmissionId=206744
+# Topcoder - Scorecard Processor
+
+## Review Processing Verification
+
+- start kafka server, start processor app
+- load Postman collection and environment in `docs` folder into Postman
+- run follow command to get a M2M token, configure it to Postman environment `TOKEN` variable:
+```
+curl --request POST --url https://topcoder-dev.auth0.com/oauth/token --header 'content-type: application/json' --data '{"client_id":"8QovDh27SrDu1XSs68m21A1NBP8isvOt","client_secret":"3QVxxu20QnagdH-McWhVz0WfsQzA1F8taDdGDI4XphgpEYZPcMTF4lX3aeOIeCzh","audience":"https://m2m.topcoder-dev.com/","grant_type":"client_credentials"}'
+```
+
+- start kafka-console-producer to write messages to `submission.notification.score` topic:
+  `bin/kafka-console-producer.sh --broker-list localhost:9092 --topic submission.notification.score`
+- write message:
+  `{ "topic": "submission.notification.score", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 85, "submissionId": 206744, "reviewId": 390088, "scorecardId": 300001610, "reviewerId": 151743, "reviewTypeId": 2, "eventType": "CREATE" } }`
+- watch the app console, it should show info of processing the message
+- Use Postman to verify the data has been updated in remote server
+  (get submission by legacy id) GET https://api.topcoder-dev.com/v5/submissions?legacySubmissionId=206744
   You will find a new review entity with score 85 in response body, you can also try the following endpoint using the review id you got from above response body
-  GET https://api.topcoder-dev.com/v5/reviews/{reviewsId}
-6. write message:
-  `{ "topic": "or.notification.create", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 90, "submissionId": 206744, "reviewId": 390088, "scorecardId": 300001610, "reviewerId": 151743, "userId": "8547899", "reviewTypeId": 2, "eventType": "UPDATE" } }`
-7. watch the app console, it should show info of processing the message
-8. repeat step 5, now the score of same review entity is 90
-9. Use Postman to clear the testing resource in remote server
+  (get review by id) GET https://api.topcoder-dev.com/v5/reviews/{reviewsId}
+  Note that there may be multiple reviews for a submission, you need to find the one matching above reviewerId and scorecardId,
+  if there are still multiple reviews, then find the latest created one.
+- write message:
+  `{ "topic": "submission.notification.score", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "score": 90, "submissionId": 206744, "reviewId": 390088, "scorecardId": 300001610, "reviewerId": 151743, "userId": "8547899", "reviewTypeId": 2, "eventType": "UPDATE" } }`
+- watch the app console, it should show info of processing the message
+- repeat above step to get review, now the score of same review entity is 90
+- Use Postman to clear the testing resource in remote server
    From step 5, you can get the reviewsId and reviewSummationId of entities that added into server just now.
-   DELETE https://api.topcoder-dev.com/v5/reviews/{reviewsId}
-   DELETE https://api.topcoder-dev.com/v5/reviewSummations/{reviewSummationId}
+   (delete review) DELETE https://api.topcoder-dev.com/v5/reviews/{reviewsId}
+   (delete review summation) DELETE https://api.topcoder-dev.com/v5/reviewSummations/{reviewSummationId}
+
+
+## Submission Processing Verification
+
+- start kafka server, start mock-scorecard-api, start processor app
+- start kafka-console-consumer to listen to topic `avscan.action.scan`:
+  `bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic avscan.action.scan --from-beginning`
+- start kafka-console-consumer to listen to topic `or.action.review`:
+  `bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic or.action.review --from-beginning`
+- start kafka-console-producer to write messages to `submission.notification.aggregate` topic:
+  `bin/kafka-console-producer.sh --broker-list localhost:9092 --topic submission.notification.aggregate`
+- write message:
+  `{ "topic": "submission.notification.aggregate", "originator": "or-app", "timestamp": "2019-02-25T00:00:00", "mime-type": "application/json", "payload": { "originalTopic": "submission.notification.create", "resource": "submission", "id": "104366f8-f46b-45db-a971-11bc69e6c8ff", "type": "Contest Submission", "url": "https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip", "memberId": 8547899, "challengeId": 30049360, "created": "2019-04-02T06:59:29.785Z", "updated": "2019-04-02T06:59:29.785Z", "createdBy": "TonyJ", "updatedBy": "TonyJ", "submissionPhaseId": 764644, "fileType": "zip", "isFileSubmission": false } }`
+- watch the app console, it should show logging of processing the message:
+```
+debug: Get M2M token
+debug: Get challenge details
+debug: Scorecard id: 30001610
+debug: Current phase: Registration
+debug: Get scorecard details
+debug: Post Kafka message for score system AV Scan: {
+    "topic": "avscan.action.scan",
+    "originator": "tc-scorecard-processor",
+    "timestamp": "2019-04-07T21:36:04.181Z",
+    "mime-type": "application/json",
+    "payload": {
+        "status": "unscanned",
+        "submissionId": "104366f8-f46b-45db-a971-11bc69e6c8ff",
+        "url": "https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip",
+        "fileName": "30054740-8547899-SUBMISSION_ZIP-1554188341581.zip"
+    }
+}
+debug: Post Kafka message for score system OR: {
+    "topic": "or.action.review",
+    "originator": "tc-scorecard-processor",
+    "timestamp": "2019-04-07T21:36:04.215Z",
+    "mime-type": "application/json",
+    "payload": {
+        "resource": "submission",
+        "id": "104366f8-f46b-45db-a971-11bc69e6c8ff",
+        "type": "Contest Submission",
+        "url": "https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip",
+        "memberId": 8547899,
+        "challengeId": 30049360,
+        "created": "2019-04-02T06:59:29.785Z",
+        "updated": "2019-04-02T06:59:29.785Z",
+        "createdBy": "TonyJ",
+        "updatedBy": "TonyJ",
+        "submissionPhaseId": 764644,
+        "fileType": "zip",
+        "isFileSubmission": false,
+        "eventType": "CREATE"
+    }
+}
+debug: EXIT processSubmission
+debug: output arguments
+debug: Successfully processed message
+```
+
+- the kafka-console-consumer listening to topic `avscan.action.scan` should show:
+```
+{"topic":"avscan.action.scan","originator":"tc-scorecard-processor","timestamp":"2019-04-07T21:36:04.181Z","mime-type":"application/json","payload":{"status":"unscanned","submissionId":"104366f8-f46b-45db-a971-11bc69e6c8ff","url":"https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip","fileName":"30054740-8547899-SUBMISSION_ZIP-1554188341581.zip"}}
+```
+
+- the kafka-console-consumer listening to topic `or.action.review` should show:
+```
+{"topic":"or.action.review","originator":"tc-scorecard-processor","timestamp":"2019-04-07T21:36:04.215Z","mime-type":"application/json","payload":{"resource":"submission","id":"104366f8-f46b-45db-a971-11bc69e6c8ff","type":"Contest Submission","url":"https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip","memberId":8547899,"challengeId":30049360,"created":"2019-04-02T06:59:29.785Z","updated":"2019-04-02T06:59:29.785Z","createdBy":"TonyJ","updatedBy":"TonyJ","submissionPhaseId":764644,"fileType":"zip","isFileSubmission":false,"eventType":"CREATE"}}
+```
+
+- the kafka-console-consumer listening to topic `avscan.action.scan` should show:
+```
+{"topic":"avscan.action.scan","originator":"tc-scorecard-processor","timestamp":"2019-04-07T21:41:52.713Z","mime-type":"application/json","payload":{"status":"unscanned","submissionId":"104366f8-f46b-45db-a971-11bc69e6c8ff","url":"https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip","fileName":"30054740-8547899-SUBMISSION_ZIP-1554188341581.zip"}}
+```
+
+- the kafka-console-consumer listening to topic `or.action.review` should show:
+```
+{"topic":"or.action.review","originator":"tc-scorecard-processor","timestamp":"2019-04-07T21:41:52.729Z","mime-type":"application/json","payload":{"resource":"submission","id":"104366f8-f46b-45db-a971-11bc69e6c8ff","type":"Contest Submission","url":"https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip","memberId":8547899,"challengeId":30049360,"created":"2019-04-02T06:59:29.785Z","updated":"2019-04-02T06:59:29.785Z","createdBy":"TonyJ","updatedBy":"TonyJ","submissionPhaseId":764644,"fileType":"zip","isFileSubmission":false,"eventType":"UPDATE"}}
+```
 
 ## Unit test Coverage
 
-  55 passing (2m)
-
-File                  |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------------|----------|----------|----------|----------|-------------------|
-All files             |    90.53 |    79.17 |    92.86 |    91.02 |                   |
- config               |      100 |      100 |      100 |      100 |                   |
-  default.js          |      100 |      100 |      100 |      100 |                   |
-  test.js             |      100 |      100 |      100 |      100 |                   |
- src                  |    93.75 |       60 |    83.33 |    93.62 |                   |
-  app.js              |    93.62 |       60 |    83.33 |    93.48 |          52,65,90 |
-  bootstrap.js        |      100 |      100 |      100 |      100 |                   |
- src/common           |    85.56 |    61.54 |       95 |    86.52 |                   |
-  helper.js           |       72 |       50 |    85.71 |       75 | 18,91,92,93,95,96 |
-  logger.js           |    90.77 |       65 |      100 |    90.77 |31,55,60,84,98,118 |
- src/services         |      100 |    92.86 |      100 |      100 |                   |
-  ProcessorService.js |      100 |    92.86 |      100 |      100 |                16 |
+  129 passing (1s)
+
+File                            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s
+--------------------------------|----------|----------|----------|----------|-------------------
+All files                       |    91.63 |    79.63 |      100 |    91.46 |
+ config                         |      100 |    96.67 |      100 |      100 |
+  default.js                    |      100 |      100 |      100 |      100 |
+  test.js                       |      100 |       50 |      100 |      100 |                 6
+ src/common                     |    92.13 |    57.69 |      100 |    91.95 |
+  helper.js                     |    95.83 |    66.67 |      100 |    95.45 |                18
+  logger.js                     |    90.77 |       55 |      100 |    90.77 |31,55,60,84,98,118
+ src/services                   |    91.07 |    80.77 |      100 |    90.91 |
+  ReviewProcessorService.js     |    97.87 |       90 |      100 |    97.83 |                72
+  SubmissionProcessorService.js |    86.15 |       75 |      100 |    85.94 |... 20,126,130,140
+
 
 ## E2E test Coverage
 
-  66 passing (2m)
-
-File                  |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------------|----------|----------|----------|----------|-------------------|
-All files             |    90.53 |    79.17 |    92.86 |    91.02 |                   |
- config               |      100 |      100 |      100 |      100 |                   |
-  default.js          |      100 |      100 |      100 |      100 |                   |
-  test.js             |      100 |      100 |      100 |      100 |                   |
- src                  |    93.75 |       60 |    83.33 |    93.62 |                   |
-  app.js              |    93.62 |       60 |    83.33 |    93.48 |          52,65,90 |
-  bootstrap.js        |      100 |      100 |      100 |      100 |                   |
- src/common           |    85.56 |    61.54 |       95 |    86.52 |                   |
-  helper.js           |       72 |       50 |    85.71 |       75 | 18,91,92,93,95,96 |
-  logger.js           |    90.77 |       65 |      100 |    90.77 |31,55,60,84,98,118 |
- src/services         |      100 |    92.86 |      100 |      100 |                   |
-  ProcessorService.js |      100 |    92.86 |      100 |      100 |                16 |
+  136 passing (5m)
+
+File                            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s
+--------------------------------|----------|----------|----------|----------|-------------------
+All files                       |    92.06 |    80.33 |    97.14 |     91.9 |
+ config                         |      100 |    96.67 |      100 |      100 |
+  default.js                    |      100 |      100 |      100 |      100 |
+  test.js                       |      100 |       50 |      100 |      100 |                 6
+ src                            |    93.88 |    71.43 |       90 |    93.75 |
+  app.js                        |    93.75 |    71.43 |       90 |    93.62 |          49,61,86
+  bootstrap.js                  |      100 |      100 |      100 |      100 |
+ src/common                     |    92.13 |    65.38 |      100 |    91.95 |
+  helper.js                     |    95.83 |    66.67 |      100 |    95.45 |                18
+  logger.js                     |    90.77 |       65 |      100 |    90.77 |31,55,60,84,98,118
+ src/services                   |    91.07 |    80.77 |      100 |    90.91 |
+  ReviewProcessorService.js     |    97.87 |       90 |      100 |    97.83 |                72
+  SubmissionProcessorService.js |    86.15 |       75 |      100 |    85.94 |... 20,126,130,140
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..aa24a4b
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+set -eo pipefail
+APP_NAME=$1
+UPDATE_CACHE=""
+docker-compose -f docker/docker-compose.yml build $APP_NAME
+docker create --name app $APP_NAME:latest
+
+if [ -d node_modules ]
+then
+  mv package-lock.json old-package-lock.json
+  docker cp app:/$APP_NAME/package-lock.json package-lock.json
+  set +eo pipefail
+  UPDATE_CACHE=$(cmp package-lock.json old-package-lock.json)
+  set -eo pipefail
+else
+  UPDATE_CACHE=1
+fi
+
+if [ "$UPDATE_CACHE" == 1 ]
+then
+  docker cp app:/$APP_NAME/node_modules .
+fi
\ No newline at end of file
diff --git a/config/default.js b/config/default.js
index f57995d..35ec49a 100644
--- a/config/default.js
+++ b/config/default.js
@@ -12,21 +12,27 @@ module.exports = {
   KAFKA_CLIENT_CERT_KEY: process.env.KAFKA_CLIENT_CERT_KEY,
 
   // Kafka group id
-  KAFKA_GROUP_ID: process.env.KAFKA_GROUP_ID || 'or-review-processor',
+  KAFKA_GROUP_ID: process.env.KAFKA_GROUP_ID || 'scorecard-processor',
 
-  // Kafka topics related to Creation and Update of review entity
-  OR_REVIEW_TOPIC: process.env.OR_REVIEW_TOPIC || 'or.notification.create',
+  // Kafka topic related to Creation and Update of review entity
+  REVIEW_TOPIC: process.env.REVIEW_TOPIC || 'submission.notification.score',
+  // Kafka topic related to create submission
+  CREATE_SUBMISSION_TOPIC: process.env.CREATE_SUBMISSION_TOPIC || 'submission.notification.create',
+  // Kafka topic related to all events related to submission
+  AGGREGATE_SUBMISSION_TOPIC: process.env.AGGREGATE_SUBMISSION_TOPIC || 'submission.notification.aggregate',
 
-  REVIEW_API_URL: process.env.REVIEW_API_URL || 'https://api.topcoder-dev.com/v5/reviews',
-  SUBMISSION_API_URL: process.env.REVIEW_API_URL || 'https://api.topcoder-dev.com/v5/submissions',
-  REVIEW_TYPE_API_URL: process.env.REVIEW_API_URL || 'https://api.topcoder-dev.com/v5/reviewTypes',
+  SUBMISSION_API_URL: process.env.SUBMISSION_API_URL || 'https://api.topcoder-dev.com/v5',
 
-  AUTH0_URL: process.env.AUTH0_URL,
+  CHALLENGE_API_URL: process.env.CHALLENGE_API_URL || 'https://api.topcoder-dev.com/v4/challenges',
+  SCORECARD_API_URL: process.env.SCORECARD_API_URL || 'http://localhost:4000/scorecards',
+  BUS_API_URL: process.env.BUS_API_URL || 'https://api.topcoder-dev.com/v5/bus/events',
+
+  AUTH0_URL: process.env.AUTH0_URL || 'https://topcoder-dev.auth0.com/oauth/token',
   AUTH0_AUDIENCE: process.env.AUTH0_AUDIENCE || 'https://m2m.topcoder-dev.com/',
   TOKEN_CACHE_TIME: process.env.TOKEN_CACHE_TIME,
-  AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID || 'enjw1810eDz3XTwSO2Rn2Y9cQTrspn3B',
-  AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET || '6wzC0_gfeuM4yEWOoobl5BylXsI44lczJjGTBABM2EJpbg9zucUwTGlgO7WWbHdt',
-  AUTH0_PROXY_SERVER_URL: process.env.AUTH0_PROXY_SERVER_URL || 'https://topcoder-dev.auth0.com/oauth/token',
+  AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID || '8QovDh27SrDu1XSs68m21A1NBP8isvOt',
+  AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET || '3QVxxu20QnagdH-McWhVz0WfsQzA1F8taDdGDI4XphgpEYZPcMTF4lX3aeOIeCzh',
+  AUTH0_PROXY_SERVER_URL: process.env.AUTH0_PROXY_SERVER_URL,
 
   // review type mapping to legacy review type id
   REVIEW_TYPES: {
diff --git a/config/test.js b/config/test.js
index a55732b..c6cd12c 100644
--- a/config/test.js
+++ b/config/test.js
@@ -3,6 +3,6 @@
  */
 
 module.exports = {
-  WAIT_TIME: 1500,
-  REVIEW_SUMMATION_API_URL: 'https://api.topcoder-dev.com/v5/reviewSummations'
+  WAIT_TIME: process.env.WAIT_TIME ? Number(process.env.WAIT_TIME) : 2000,
+  SCORECARD_API_URL: 'https://api.topcoder-dev.com/v5/scorecards'
 }
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..5daea05
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,17 @@
+# Use the base image with Node.js
+FROM node:latest
+
+# Copy the current directory into the Docker image
+COPY . /or-review-processor
+
+# Set working directory for future use
+WORKDIR /or-review-processor
+
+# Install the dependencies from package.json
+RUN npm install
+RUN npm run lint
+RUN npm run lint:fix
+#RUN npm run build
+RUN npm run test
+
+CMD npm start
\ No newline at end of file
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
new file mode 100644
index 0000000..456253f
--- /dev/null
+++ b/docker/docker-compose.yml
@@ -0,0 +1,7 @@
+version: '3'
+services:
+  or-review-processor:
+    image: or-review-processor:latest
+    build:
+      context: ../
+      dockerfile: docker/Dockerfile
diff --git a/docs/scorecard-processor-env.postman_environment.json b/docs/scorecard-processor-env.postman_environment.json
new file mode 100644
index 0000000..f9edc79
--- /dev/null
+++ b/docs/scorecard-processor-env.postman_environment.json
@@ -0,0 +1,20 @@
+{
+	"id": "7cf2fed4-7162-4ce9-a8f6-c44de383c2e8",
+	"name": "scorecard-processor-env",
+	"values": [
+		{
+			"key": "TOKEN",
+			"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5VSkZORGd4UlRVME5EWTBOVVkzTlRkR05qTXlRamxETmpOQk5UYzVRVUV3UlRFeU56TTJRUSJ9.eyJpc3MiOiJodHRwczovL3RvcGNvZGVyLWRldi5hdXRoMC5jb20vIiwic3ViIjoiOFFvdkRoMjdTckR1MVhTczY4bTIxQTFOQlA4aXN2T3RAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbTJtLnRvcGNvZGVyLWRldi5jb20vIiwiaWF0IjoxNTU0NjQyNTk0LCJleHAiOjE1NTQ3Mjg5OTQsImF6cCI6IjhRb3ZEaDI3U3JEdTFYU3M2OG0yMUExTkJQOGlzdk90Iiwic2NvcGUiOiJyZWFkOmNoYWxsZW5nZXMgcmVhZDpncm91cHMgcmVhZDpzdWJtaXNzaW9uIHJlYWQ6cmV2aWV3X3R5cGUgdXBkYXRlOnJldmlld19zdW1tYXRpb24gcmVhZDpyZXZpZXdfc3VtbWF0aW9uIGNyZWF0ZTpyZXZpZXdfc3VtbWF0aW9uIHVwZGF0ZTpyZXZpZXcgcmVhZDpyZXZpZXcgZGVsZXRlOnJldmlldyBjcmVhdGU6cmV2aWV3IGFsbDpyZXZpZXcgcmVhZDpwcm9qZWN0IHdyaXRlOmJ1c19hcGkgcmVhZDp1c2VyX3Byb2ZpbGVzIHJlYWQ6cm9sZXMiLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.m2ie6HzQhUIBHUVoBWHliDRPbgBH1aVc-WWLFdGm8HBtz6KpIRRQHC8CMLmyn1fbZrkciAzpXbbY3XaVAVB_5C6yv3kV6JHnIg34n0l5AZB1ubzpNdVeNFKfA3J1uDWPzQf5HWTkZkxVd8E5hCZWwD0bmXlzUFNaNDDeBp6DSOSAGwGgLWTkEgkle43YVtx4eJjAsvjtOGgHOSabEJZ2KeDLsV6UHYjL8KKFMqENN3k5Qx5NZXlOfUd9V7tW_wH5zaB5nj43TdOEnp8izEmtU3ybIBBxuU8HybTemv6RP9AsZyq32wuq0IlH3DJP0bLk7uyDWHkJbwrGVJVGl3-aEQ",
+			"enabled": true
+		},
+		{
+			"key": "URL",
+			"value": "https://api.topcoder-dev.com/v5",
+			"description": "",
+			"enabled": true
+		}
+	],
+	"_postman_variable_scope": "environment",
+	"_postman_exported_at": "2019-04-08T20:52:21.290Z",
+	"_postman_exported_using": "Postman/6.4.4"
+}
\ No newline at end of file
diff --git a/docs/scorecard-processor.postman_collection.json b/docs/scorecard-processor.postman_collection.json
new file mode 100644
index 0000000..cc45a67
--- /dev/null
+++ b/docs/scorecard-processor.postman_collection.json
@@ -0,0 +1,207 @@
+{
+	"info": {
+		"_postman_id": "5fd86bd3-51b3-491c-8e1f-cc221f6f895f",
+		"name": "scorecard-processor",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+	},
+	"item": [
+		{
+			"name": "review-processing",
+			"item": [
+				{
+					"name": "get submission by legacy id",
+					"request": {
+						"method": "GET",
+						"header": [
+							{
+								"key": "Accept",
+								"value": "application/json"
+							},
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"value": "Bearer {{TOKEN}}",
+								"type": "text"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": ""
+						},
+						"url": {
+							"raw": "{{URL}}/submissions?legacySubmissionId=206744",
+							"host": [
+								"{{URL}}"
+							],
+							"path": [
+								"submissions"
+							],
+							"query": [
+								{
+									"key": "legacySubmissionId",
+									"value": "206744"
+								}
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "get review by id",
+					"request": {
+						"method": "GET",
+						"header": [
+							{
+								"key": "Accept",
+								"value": "application/json"
+							},
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{TOKEN}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": ""
+						},
+						"url": {
+							"raw": "{{URL}}/reviews/9e82af32-da73-4610-a4a1-593b74c83a25",
+							"host": [
+								"{{URL}}"
+							],
+							"path": [
+								"reviews",
+								"9e82af32-da73-4610-a4a1-593b74c83a25"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "delete review",
+					"request": {
+						"method": "DELETE",
+						"header": [
+							{
+								"key": "Accept",
+								"value": "application/json"
+							},
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{TOKEN}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": ""
+						},
+						"url": {
+							"raw": "{{URL}}/reviews/9e82af32-da73-4610-a4a1-593b74c83a25",
+							"host": [
+								"{{URL}}"
+							],
+							"path": [
+								"reviews",
+								"9e82af32-da73-4610-a4a1-593b74c83a25"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "delete review summation",
+					"request": {
+						"method": "DELETE",
+						"header": [
+							{
+								"key": "Accept",
+								"value": "application/json"
+							},
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Authorization",
+								"type": "text",
+								"value": "Bearer {{TOKEN}}"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": ""
+						},
+						"url": {
+							"raw": "{{URL}}/reviewSummations/32050c81-d2a4-4413-ba43-262d1fc1ead7",
+							"host": [
+								"{{URL}}"
+							],
+							"path": [
+								"reviewSummations",
+								"32050c81-d2a4-4413-ba43-262d1fc1ead7"
+							]
+						}
+					},
+					"response": []
+				}
+			],
+			"event": [
+				{
+					"listen": "prerequest",
+					"script": {
+						"id": "4b651537-6c26-4f18-ae6d-6f3c53aa7f18",
+						"type": "text/javascript",
+						"exec": [
+							""
+						]
+					}
+				},
+				{
+					"listen": "test",
+					"script": {
+						"id": "1f50ae8d-c7dd-46d6-9b99-6c69b641ee3d",
+						"type": "text/javascript",
+						"exec": [
+							""
+						]
+					}
+				}
+			]
+		}
+	],
+	"event": [
+		{
+			"listen": "prerequest",
+			"script": {
+				"id": "4e396df5-d3a4-4c5f-8477-eeead6536fd5",
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		},
+		{
+			"listen": "test",
+			"script": {
+				"id": "683c9325-3bdf-4d2f-89f2-6e2e4f5c854f",
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/mock-scorecard-api/README.md b/mock-scorecard-api/README.md
new file mode 100755
index 0000000..cb70560
--- /dev/null
+++ b/mock-scorecard-api/README.md
@@ -0,0 +1,18 @@
+# Scorecard mock API
+
+## Dependencies
+
+- nodejs https://nodejs.org/en/ (v10+)
+
+
+## Local setup
+
+Run `npm i` to install the dependencies and `npm start` to start the mock API.
+And the app is running at `http://localhost:4000`.
+
+
+## Endpoints
+
+- `/scoreSystems` - returns the score systems
+- `/scorecards/:id` - returns the details for a specific scorecard
+
diff --git a/mock-scorecard-api/data/scoreSystems.json b/mock-scorecard-api/data/scoreSystems.json
new file mode 100755
index 0000000..bcf9616
--- /dev/null
+++ b/mock-scorecard-api/data/scoreSystems.json
@@ -0,0 +1,30 @@
+[
+  {
+    "id": "b9956051-4749-4912-abd1-af4d701af891",
+    "name": "AV Scan",
+    "phase": "submission",
+    "isActive": true,
+    "topic": "avscan.action.scan"
+  },
+  {
+    "id": "b9956051-4749-4912-abd1-af4d701af892",
+    "name": "OR",
+    "phase": "review",
+    "isActive": true,
+    "topic": "or.action.review"
+  },
+  {
+    "id": "b9956051-4749-4912-abd1-af4d701af893",
+    "name": "AV Scan",
+    "phase": "registration",
+    "isActive": true,
+    "topic": "avscan.action.scan"
+  },
+  {
+    "id": "b9956051-4749-4912-abd1-af4d701af894",
+    "name": "OR",
+    "phase": "registration",
+    "isActive": true,
+    "topic": "or.action.review"
+  }
+]
diff --git a/mock-scorecard-api/data/scorecardDetails.json b/mock-scorecard-api/data/scorecardDetails.json
new file mode 100755
index 0000000..2cfab2c
--- /dev/null
+++ b/mock-scorecard-api/data/scorecardDetails.json
@@ -0,0 +1,3 @@
+{
+  "id": "b9956051-4749-4912-abd5-bf4d701af891"
+}
diff --git a/mock-scorecard-api/index.js b/mock-scorecard-api/index.js
new file mode 100755
index 0000000..90631af
--- /dev/null
+++ b/mock-scorecard-api/index.js
@@ -0,0 +1,19 @@
+const express = require('express')
+const scoreSystems = require('./data/scoreSystems.json')
+const scorecardDetails = require('./data/scorecardDetails.json')
+const app = express()
+
+scorecardDetails.scorecardDetails = []
+
+scoreSystems.forEach(element => {
+  scorecardDetails.scorecardDetails.push({
+    ...element,
+    weight: 100 / scoreSystems.length
+  })
+})
+
+app.get('/scoreSystems', (req, res) => res.json(scoreSystems))
+app.get('/scorecards/:id', (req, res) => res.json(scorecardDetails))
+
+app.listen(process.env.PORT || 4000)
+console.log(`Server listening on http://localhost:${process.env.PORT || 4000}`)
diff --git a/mock-scorecard-api/package-lock.json b/mock-scorecard-api/package-lock.json
new file mode 100755
index 0000000..f259261
--- /dev/null
+++ b/mock-scorecard-api/package-lock.json
@@ -0,0 +1,358 @@
+{
+  "name": "mock-scorecard-api",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "accepts": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "requires": {
+        "mime-types": "~2.1.18",
+        "negotiator": "0.6.1"
+      }
+    },
+    "array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+    },
+    "body-parser": {
+      "version": "1.18.3",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+      "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+      "requires": {
+        "bytes": "3.0.0",
+        "content-type": "~1.0.4",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "http-errors": "~1.6.3",
+        "iconv-lite": "0.4.23",
+        "on-finished": "~2.3.0",
+        "qs": "6.5.2",
+        "raw-body": "2.3.3",
+        "type-is": "~1.6.16"
+      }
+    },
+    "bytes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+    },
+    "content-disposition": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+    },
+    "cookie": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+    },
+    "cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+    },
+    "debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+    },
+    "express": {
+      "version": "4.16.4",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+      "requires": {
+        "accepts": "~1.3.5",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.18.3",
+        "content-disposition": "0.5.2",
+        "content-type": "~1.0.4",
+        "cookie": "0.3.1",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "1.1.1",
+        "fresh": "0.5.2",
+        "merge-descriptors": "1.0.1",
+        "methods": "~1.1.2",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.2",
+        "path-to-regexp": "0.1.7",
+        "proxy-addr": "~2.0.4",
+        "qs": "6.5.2",
+        "range-parser": "~1.2.0",
+        "safe-buffer": "5.1.2",
+        "send": "0.16.2",
+        "serve-static": "1.13.2",
+        "setprototypeof": "1.1.0",
+        "statuses": "~1.4.0",
+        "type-is": "~1.6.16",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+      "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.2",
+        "statuses": "~1.4.0",
+        "unpipe": "~1.0.0"
+      }
+    },
+    "forwarded": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+    },
+    "http-errors": {
+      "version": "1.6.3",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+      "requires": {
+        "depd": "~1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.0",
+        "statuses": ">= 1.4.0 < 2"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.23",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "ipaddr.js": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
+      "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "mime": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+      "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+    },
+    "mime-db": {
+      "version": "1.38.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
+      "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
+    },
+    "mime-types": {
+      "version": "2.1.22",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
+      "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+      "requires": {
+        "mime-db": "~1.38.0"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "negotiator": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+    },
+    "path-to-regexp": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+    },
+    "proxy-addr": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
+      "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+      "requires": {
+        "forwarded": "~0.1.2",
+        "ipaddr.js": "1.8.0"
+      }
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+    },
+    "range-parser": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+    },
+    "raw-body": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+      "requires": {
+        "bytes": "3.0.0",
+        "http-errors": "1.6.3",
+        "iconv-lite": "0.4.23",
+        "unpipe": "1.0.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "send": {
+      "version": "0.16.2",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+      "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+      "requires": {
+        "debug": "2.6.9",
+        "depd": "~1.1.2",
+        "destroy": "~1.0.4",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "~1.6.2",
+        "mime": "1.4.1",
+        "ms": "2.0.0",
+        "on-finished": "~2.3.0",
+        "range-parser": "~1.2.0",
+        "statuses": "~1.4.0"
+      }
+    },
+    "serve-static": {
+      "version": "1.13.2",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+      "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+      "requires": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.2",
+        "send": "0.16.2"
+      }
+    },
+    "setprototypeof": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+    },
+    "statuses": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+      "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+    },
+    "type-is": {
+      "version": "1.6.16",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.18"
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+    },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+    },
+    "vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+    }
+  }
+}
diff --git a/mock-scorecard-api/package.json b/mock-scorecard-api/package.json
new file mode 100755
index 0000000..5de8571
--- /dev/null
+++ b/mock-scorecard-api/package.json
@@ -0,0 +1,14 @@
+{
+  "name": "mock-scorecard-api",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "start": "node index.js"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "express": "^4.16.4"
+  }
+}
diff --git a/package-lock.json b/package-lock.json
index 59d09cd..f950199 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,167 +5,283 @@
   "requires": true,
   "dependencies": {
     "@babel/code-frame": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
-      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
+      "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==",
       "dev": true,
       "requires": {
-        "@babel/highlight": "^7.0.0"
+        "@babel/highlight": "^7.14.5"
       }
     },
     "@babel/generator": {
-      "version": "7.3.4",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz",
-      "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz",
+      "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.3.4",
+        "@babel/types": "^7.14.5",
         "jsesc": "^2.5.1",
-        "lodash": "^4.17.11",
-        "source-map": "^0.5.0",
-        "trim-right": "^1.0.1"
+        "source-map": "^0.5.0"
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
-      "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz",
+      "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==",
       "dev": true,
       "requires": {
-        "@babel/helper-get-function-arity": "^7.0.0",
-        "@babel/template": "^7.1.0",
-        "@babel/types": "^7.0.0"
+        "@babel/helper-get-function-arity": "^7.14.5",
+        "@babel/template": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-get-function-arity": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
-      "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz",
+      "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.14.5"
+      }
+    },
+    "@babel/helper-hoist-variables": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz",
+      "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.0.0"
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/helper-split-export-declaration": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
-      "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz",
+      "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.0.0"
+        "@babel/types": "^7.14.5"
       }
     },
+    "@babel/helper-validator-identifier": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
+      "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
+      "dev": true
+    },
     "@babel/highlight": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
-      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
+      "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
       "dev": true,
       "requires": {
+        "@babel/helper-validator-identifier": "^7.14.5",
         "chalk": "^2.0.0",
-        "esutils": "^2.0.2",
         "js-tokens": "^4.0.0"
-      },
-      "dependencies": {
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
-        }
       }
     },
     "@babel/parser": {
-      "version": "7.3.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz",
-      "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==",
+      "version": "7.14.6",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz",
+      "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==",
       "dev": true
     },
     "@babel/template": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz",
-      "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz",
+      "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "@babel/parser": "^7.2.2",
-        "@babel/types": "^7.2.2"
+        "@babel/code-frame": "^7.14.5",
+        "@babel/parser": "^7.14.5",
+        "@babel/types": "^7.14.5"
       }
     },
     "@babel/traverse": {
-      "version": "7.3.4",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz",
-      "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz",
+      "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.0.0",
-        "@babel/generator": "^7.3.4",
-        "@babel/helper-function-name": "^7.1.0",
-        "@babel/helper-split-export-declaration": "^7.0.0",
-        "@babel/parser": "^7.3.4",
-        "@babel/types": "^7.3.4",
+        "@babel/code-frame": "^7.14.5",
+        "@babel/generator": "^7.14.5",
+        "@babel/helper-function-name": "^7.14.5",
+        "@babel/helper-hoist-variables": "^7.14.5",
+        "@babel/helper-split-export-declaration": "^7.14.5",
+        "@babel/parser": "^7.14.5",
+        "@babel/types": "^7.14.5",
         "debug": "^4.1.0",
-        "globals": "^11.1.0",
-        "lodash": "^4.17.11"
+        "globals": "^11.1.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
       }
     },
     "@babel/types": {
-      "version": "7.3.4",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz",
-      "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==",
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz",
+      "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==",
       "dev": true,
       "requires": {
-        "esutils": "^2.0.2",
-        "lodash": "^4.17.11",
+        "@babel/helper-validator-identifier": "^7.14.5",
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@dabh/diagnostics": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz",
+      "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==",
+      "requires": {
+        "colorspace": "1.1.x",
+        "enabled": "2.0.x",
+        "kuler": "^2.0.0"
+      }
+    },
+    "@hapi/address": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
+      "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ=="
+    },
+    "@hapi/bourne": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz",
+      "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA=="
+    },
+    "@hapi/hoek": {
+      "version": "8.5.1",
+      "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz",
+      "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow=="
+    },
+    "@hapi/joi": {
+      "version": "15.1.1",
+      "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz",
+      "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==",
+      "requires": {
+        "@hapi/address": "2.x.x",
+        "@hapi/bourne": "1.x.x",
+        "@hapi/hoek": "8.x.x",
+        "@hapi/topo": "3.x.x"
+      }
+    },
+    "@hapi/topo": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz",
+      "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==",
+      "requires": {
+        "@hapi/hoek": "^8.3.0"
+      }
+    },
+    "@tootallnate/once": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+      "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
+    },
+    "@topcoder-platform/topcoder-submission-api-wrapper": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@topcoder-platform/topcoder-submission-api-wrapper/-/topcoder-submission-api-wrapper-1.2.0.tgz",
+      "integrity": "sha512-Zfro6a2sfUA12zTLbxs3sNLk0nr44fmrjLtMKTlmNhMEM5dq6uhvro+W7h76kjGGyX8VzlPYdzTDHmWS6wr9rg==",
+      "requires": {
+        "@hapi/joi": "^15.0.3",
+        "lodash": "^4.17.15",
+        "superagent": "^3.8.3",
+        "tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.4"
+      },
+      "dependencies": {
+        "superagent": {
+          "version": "3.8.3",
+          "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
+          "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
+          "requires": {
+            "component-emitter": "^1.2.0",
+            "cookiejar": "^2.1.0",
+            "debug": "^3.1.0",
+            "extend": "^3.0.0",
+            "form-data": "^2.3.1",
+            "formidable": "^1.2.0",
+            "methods": "^1.1.1",
+            "mime": "^1.4.1",
+            "qs": "^6.5.1",
+            "readable-stream": "^2.3.5"
+          }
+        },
+        "tc-core-library-js": {
+          "version": "github:appirio-tech/tc-core-library-js#df0b36c51cf80918194cbff777214b3c0cf5a151",
+          "from": "github:appirio-tech/tc-core-library-js#v2.6.4",
+          "requires": {
+            "axios": "^0.19.0",
+            "bunyan": "^1.8.12",
+            "jsonwebtoken": "^8.5.1",
+            "jwks-rsa": "^1.6.0",
+            "lodash": "^4.17.15",
+            "millisecond": "^0.1.2",
+            "r7insight_node": "^1.8.4",
+            "request": "^2.88.0"
+          }
+        }
+      }
+    },
     "@types/bluebird": {
       "version": "3.5.0",
       "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.0.tgz",
       "integrity": "sha1-JjNHCk6r6aR82aRf2yDtX5NAe8o="
     },
     "@types/body-parser": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz",
-      "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==",
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
       "requires": {
         "@types/connect": "*",
         "@types/node": "*"
       }
     },
     "@types/connect": {
-      "version": "3.4.32",
-      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
-      "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
+      "version": "3.4.34",
+      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
+      "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
       "requires": {
         "@types/node": "*"
       }
     },
     "@types/express": {
-      "version": "4.16.1",
-      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz",
-      "integrity": "sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==",
+      "version": "4.17.12",
+      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz",
+      "integrity": "sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==",
       "requires": {
         "@types/body-parser": "*",
-        "@types/express-serve-static-core": "*",
+        "@types/express-serve-static-core": "^4.17.18",
+        "@types/qs": "*",
         "@types/serve-static": "*"
       }
     },
     "@types/express-jwt": {
-      "version": "0.0.34",
-      "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.34.tgz",
-      "integrity": "sha1-/b7kxq9cCiRu8qkz9VGZc8dxfwI=",
+      "version": "0.0.42",
+      "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz",
+      "integrity": "sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==",
       "requires": {
         "@types/express": "*",
         "@types/express-unless": "*"
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.16.1",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.1.tgz",
-      "integrity": "sha512-QgbIMRU1EVRry5cIu1ORCQP4flSYqLM1lS5LYyGWfKnFT3E58f0gKto7BR13clBFVrVZ0G0rbLZ1hUpSkgQQOA==",
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz",
+      "integrity": "sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==",
       "requires": {
         "@types/node": "*",
+        "@types/qs": "*",
         "@types/range-parser": "*"
       }
     },
@@ -178,19 +294,24 @@
       }
     },
     "@types/lodash": {
-      "version": "4.14.121",
-      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz",
-      "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ=="
+      "version": "4.14.170",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
+      "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q=="
     },
     "@types/mime": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
-      "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw=="
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
+      "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
     },
     "@types/node": {
-      "version": "11.9.5",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.5.tgz",
-      "integrity": "sha512-vVjM0SVzgaOUpflq4GYBvCpozes8OgIIS5gVXVka+OfK3hvnkC1i93U8WiY2OtNE4XUWyyy/86Kf6e0IHTQw1Q=="
+      "version": "15.12.2",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
+      "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww=="
+    },
+    "@types/qs": {
+      "version": "6.9.6",
+      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz",
+      "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA=="
     },
     "@types/range-parser": {
       "version": "1.2.3",
@@ -198,61 +319,73 @@
       "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
     },
     "@types/serve-static": {
-      "version": "1.13.2",
-      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz",
-      "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==",
+      "version": "1.13.9",
+      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
+      "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==",
       "requires": {
-        "@types/express-serve-static-core": "*",
-        "@types/mime": "*"
+        "@types/mime": "^1",
+        "@types/node": "*"
       }
     },
     "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+      "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
       "requires": {
-        "mime-types": "~2.1.18",
-        "negotiator": "0.6.1"
+        "mime-types": "~2.1.24",
+        "negotiator": "0.6.2"
       }
     },
     "acorn": {
-      "version": "5.7.3",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
-      "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
+      "version": "6.4.2",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+      "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
       "dev": true
     },
     "acorn-jsx": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
-      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
-      "dev": true,
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+      "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+      "dev": true
+    },
+    "agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
       "requires": {
-        "acorn": "^3.0.4"
+        "debug": "4"
       },
       "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
-          "dev": true
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
         }
       }
     },
     "ajv": {
-      "version": "6.9.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.2.tgz",
-      "integrity": "sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg==",
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
       "requires": {
-        "fast-deep-equal": "^2.0.1",
+        "fast-deep-equal": "^3.1.1",
         "fast-json-stable-stringify": "^2.0.0",
         "json-schema-traverse": "^0.4.1",
         "uri-js": "^4.2.2"
       }
     },
     "ajv-keywords": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
-      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
       "dev": true
     },
     "ansi-escapes": {
@@ -291,13 +424,16 @@
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
     },
     "array-includes": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
-      "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz",
+      "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==",
       "dev": true,
       "requires": {
-        "define-properties": "^1.1.2",
-        "es-abstract": "^1.7.0"
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.18.0-next.2",
+        "get-intrinsic": "^1.1.1",
+        "is-string": "^1.0.5"
       }
     },
     "asn1": {
@@ -314,102 +450,31 @@
       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
     },
     "async": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
-      "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
-      "requires": {
-        "lodash": "^4.17.11"
-      }
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
+      "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
     },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
     },
-    "auth0-js": {
-      "version": "9.10.0",
-      "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.10.0.tgz",
-      "integrity": "sha512-cHE4cGQRMjCS6IorIWdH2wdYSpDQchHq/xQOn7FlEaquDrb2zgQi4G5AWzO7wW2ED4UZsX4rHElc2BMZev8rGA==",
-      "requires": {
-        "base64-js": "^1.2.0",
-        "idtoken-verifier": "^1.2.0",
-        "js-cookie": "^2.2.0",
-        "qs": "^6.4.0",
-        "superagent": "^3.8.2",
-        "url-join": "^4.0.0",
-        "winchan": "^0.2.1"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "mime": {
-          "version": "1.6.0",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-          "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        },
-        "superagent": {
-          "version": "3.8.3",
-          "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
-          "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
-          "requires": {
-            "component-emitter": "^1.2.0",
-            "cookiejar": "^2.1.0",
-            "debug": "^3.1.0",
-            "extend": "^3.0.0",
-            "form-data": "^2.3.1",
-            "formidable": "^1.2.0",
-            "methods": "^1.1.1",
-            "mime": "^1.4.1",
-            "qs": "^6.5.1",
-            "readable-stream": "^2.3.5"
-          }
-        }
-      }
-    },
     "aws-sign2": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
     },
     "aws4": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+      "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
     },
     "axios": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-0.12.0.tgz",
-      "integrity": "sha1-uQewIhzDTsHJ+sGOx/B935V4W6Q=",
+      "version": "0.19.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
+      "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
       "requires": {
-        "follow-redirects": "0.0.7"
+        "follow-redirects": "1.5.10"
       }
     },
     "babel-code-frame": {
@@ -442,6 +507,12 @@
             "supports-color": "^2.0.0"
           }
         },
+        "js-tokens": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+          "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+          "dev": true
+        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -476,14 +547,9 @@
       }
     },
     "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
-    },
-    "base64-js": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
-      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
@@ -504,25 +570,25 @@
       }
     },
     "bluebird": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
-      "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
     },
     "body-parser": {
-      "version": "1.18.3",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
-      "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+      "version": "1.19.0",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
       "requires": {
-        "bytes": "3.0.0",
+        "bytes": "3.1.0",
         "content-type": "~1.0.4",
         "debug": "2.6.9",
         "depd": "~1.1.2",
-        "http-errors": "~1.6.3",
-        "iconv-lite": "0.4.23",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
         "on-finished": "~2.3.0",
-        "qs": "6.5.2",
-        "raw-body": "2.3.3",
-        "type-is": "~1.6.16"
+        "qs": "6.7.0",
+        "raw-body": "2.4.0",
+        "type-is": "~1.6.17"
       },
       "dependencies": {
         "debug": {
@@ -539,9 +605,9 @@
           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
         },
         "qs": {
-          "version": "6.5.2",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+          "version": "6.7.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
         }
       }
     },
@@ -570,33 +636,30 @@
       "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
       "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
     },
-    "buffer-from": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
-      "dev": true
-    },
-    "builtin-modules": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-      "dev": true
-    },
     "bunyan": {
-      "version": "1.8.12",
-      "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
-      "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
+      "version": "1.8.15",
+      "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz",
+      "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==",
       "requires": {
         "dtrace-provider": "~0.8",
-        "moment": "^2.10.6",
+        "moment": "^2.19.3",
         "mv": "~2",
         "safe-json-stringify": "~1"
       }
     },
     "bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+      "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+    },
+    "call-bind": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+      "requires": {
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.0.2"
+      }
     },
     "caller-path": {
       "version": "0.1.0",
@@ -651,15 +714,9 @@
       }
     },
     "cli-width": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
-      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
-      "dev": true
-    },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
+      "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
       "dev": true
     },
     "codependency": {
@@ -700,37 +757,32 @@
       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
     "color-string": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
-      "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
+      "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
       "requires": {
         "color-name": "^1.0.0",
         "simple-swizzle": "^0.2.2"
       }
     },
-    "colornames": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
-      "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
-    },
     "colors": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
-      "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
     },
     "colorspace": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz",
-      "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz",
+      "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==",
       "requires": {
         "color": "3.0.x",
         "text-hex": "1.0.x"
       }
     },
     "combined-stream": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
-      "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
       "requires": {
         "delayed-stream": "~1.0.0"
       }
@@ -742,59 +794,21 @@
       "dev": true
     },
     "component-emitter": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
-      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
     },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
-    "concat-stream": {
-      "version": "1.6.2",
-      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
-      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
-      "dev": true,
-      "requires": {
-        "buffer-from": "^1.0.0",
-        "inherits": "^2.0.3",
-        "readable-stream": "^2.2.2",
-        "typedarray": "^0.0.6"
-      },
-      "dependencies": {
-        "readable-stream": {
-          "version": "2.3.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-          "dev": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "dev": true,
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        }
-      }
-    },
     "config": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/config/-/config-3.0.1.tgz",
-      "integrity": "sha512-TBNrrk2b6AybUohqXw2AydglFBL9b/+1GG93Di6Fm6x1SyVJ5PYgo+mqY2X0KpU9m0PJDSbFaC5H95utSphtLw==",
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz",
+      "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==",
       "requires": {
-        "json5": "^1.0.1"
+        "json5": "^2.1.1"
       }
     },
     "connection-parse": {
@@ -809,9 +823,12 @@
       "dev": true
     },
     "content-disposition": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
-      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+      "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+      "requires": {
+        "safe-buffer": "5.1.2"
+      }
     },
     "content-type": {
       "version": "1.0.4",
@@ -819,9 +836,9 @@
       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
     },
     "cookie": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
-      "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+      "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
     },
     "cookie-signature": {
       "version": "1.0.6",
@@ -834,9 +851,9 @@
       "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
     },
     "core-js": {
-      "version": "2.6.5",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
-      "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
+      "version": "2.6.12",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
     },
     "core-util-is": {
       "version": "1.0.2",
@@ -844,21 +861,18 @@
       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
     },
     "cross-spawn": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
-      "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+      "version": "6.0.5",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
       "dev": true,
       "requires": {
-        "lru-cache": "^4.0.1",
+        "nice-try": "^1.0.4",
+        "path-key": "^2.0.1",
+        "semver": "^5.5.0",
         "shebang-command": "^1.2.0",
         "which": "^1.2.9"
       }
     },
-    "crypto-js": {
-      "version": "3.1.9-1",
-      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
-      "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
-    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -868,9 +882,9 @@
       }
     },
     "debug": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
       "requires": {
         "ms": "^2.1.1"
       }
@@ -911,9 +925,9 @@
       },
       "dependencies": {
         "glob": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+          "version": "7.1.7",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+          "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
           "dev": true,
           "requires": {
             "fs.realpath": "^1.0.0",
@@ -923,6 +937,12 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "ignore": {
+          "version": "3.3.10",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+          "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+          "dev": true
         }
       }
     },
@@ -941,16 +961,6 @@
       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
     },
-    "diagnostics": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
-      "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
-      "requires": {
-        "colorspace": "1.1.x",
-        "enabled": "1.0.x",
-        "kuler": "1.0.x"
-      }
-    },
     "diff": {
       "version": "3.5.0",
       "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
@@ -967,12 +977,12 @@
       }
     },
     "dtrace-provider": {
-      "version": "0.8.7",
-      "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz",
-      "integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=",
+      "version": "0.8.8",
+      "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
+      "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
       "optional": true,
       "requires": {
-        "nan": "^2.10.0"
+        "nan": "^2.14.0"
       }
     },
     "ecc-jsbn": {
@@ -998,23 +1008,15 @@
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
     "enabled": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
-      "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
-      "requires": {
-        "env-variable": "0.0.x"
-      }
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
+      "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
     },
     "encodeurl": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
     },
-    "env-variable": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
-      "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA=="
-    },
     "error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -1033,23 +1035,33 @@
       }
     },
     "es-abstract": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
-      "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+      "version": "1.18.3",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
+      "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
       "dev": true,
       "requires": {
-        "es-to-primitive": "^1.2.0",
+        "call-bind": "^1.0.2",
+        "es-to-primitive": "^1.2.1",
         "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.1.1",
         "has": "^1.0.3",
-        "is-callable": "^1.1.4",
-        "is-regex": "^1.0.4",
-        "object-keys": "^1.0.12"
+        "has-symbols": "^1.0.2",
+        "is-callable": "^1.2.3",
+        "is-negative-zero": "^2.0.1",
+        "is-regex": "^1.1.3",
+        "is-string": "^1.0.6",
+        "object-inspect": "^1.10.3",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.2",
+        "string.prototype.trimend": "^1.0.4",
+        "string.prototype.trimstart": "^1.0.4",
+        "unbox-primitive": "^1.0.1"
       }
     },
     "es-to-primitive": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
-      "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
       "dev": true,
       "requires": {
         "is-callable": "^1.1.4",
@@ -1069,81 +1081,55 @@
       "dev": true
     },
     "eslint": {
-      "version": "4.18.2",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz",
-      "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz",
+      "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==",
       "dev": true,
       "requires": {
-        "ajv": "^5.3.0",
-        "babel-code-frame": "^6.22.0",
+        "ajv": "^6.5.0",
+        "babel-code-frame": "^6.26.0",
         "chalk": "^2.1.0",
-        "concat-stream": "^1.6.0",
-        "cross-spawn": "^5.1.0",
+        "cross-spawn": "^6.0.5",
         "debug": "^3.1.0",
         "doctrine": "^2.1.0",
-        "eslint-scope": "^3.7.1",
+        "eslint-scope": "^4.0.0",
+        "eslint-utils": "^1.3.1",
         "eslint-visitor-keys": "^1.0.0",
-        "espree": "^3.5.2",
-        "esquery": "^1.0.0",
+        "espree": "^4.0.0",
+        "esquery": "^1.0.1",
         "esutils": "^2.0.2",
         "file-entry-cache": "^2.0.0",
         "functional-red-black-tree": "^1.0.1",
         "glob": "^7.1.2",
-        "globals": "^11.0.1",
-        "ignore": "^3.3.3",
+        "globals": "^11.7.0",
+        "ignore": "^4.0.2",
         "imurmurhash": "^0.1.4",
-        "inquirer": "^3.0.6",
-        "is-resolvable": "^1.0.0",
-        "js-yaml": "^3.9.1",
+        "inquirer": "^5.2.0",
+        "is-resolvable": "^1.1.0",
+        "js-yaml": "^3.11.0",
         "json-stable-stringify-without-jsonify": "^1.0.1",
         "levn": "^0.3.0",
-        "lodash": "^4.17.4",
-        "minimatch": "^3.0.2",
+        "lodash": "^4.17.5",
+        "minimatch": "^3.0.4",
         "mkdirp": "^0.5.1",
         "natural-compare": "^1.4.0",
         "optionator": "^0.8.2",
         "path-is-inside": "^1.0.2",
         "pluralize": "^7.0.0",
         "progress": "^2.0.0",
+        "regexpp": "^2.0.0",
         "require-uncached": "^1.0.3",
-        "semver": "^5.3.0",
+        "semver": "^5.5.0",
         "strip-ansi": "^4.0.0",
-        "strip-json-comments": "~2.0.1",
-        "table": "4.0.2",
-        "text-table": "~0.2.0"
+        "strip-json-comments": "^2.0.1",
+        "table": "^4.0.3",
+        "text-table": "^0.2.0"
       },
       "dependencies": {
-        "ajv": {
-          "version": "5.5.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-          "dev": true,
-          "requires": {
-            "co": "^4.6.0",
-            "fast-deep-equal": "^1.0.0",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.3.0"
-          }
-        },
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "dev": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "fast-deep-equal": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-          "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-          "dev": true
-        },
         "glob": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+          "version": "7.1.7",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+          "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
           "dev": true,
           "requires": {
             "fs.realpath": "^1.0.0",
@@ -1153,35 +1139,29 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
-        },
-        "json-schema-traverse": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-          "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-          "dev": true
         }
       }
     },
     "eslint-config-standard": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz",
-      "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==",
+      "version": "12.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz",
+      "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==",
       "dev": true
     },
     "eslint-config-standard-jsx": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz",
-      "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==",
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz",
+      "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==",
       "dev": true
     },
     "eslint-import-resolver-node": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
-      "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz",
+      "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==",
       "dev": true,
       "requires": {
         "debug": "^2.6.9",
-        "resolve": "^1.5.0"
+        "resolve": "^1.13.1"
       },
       "dependencies": {
         "debug": {
@@ -1202,48 +1182,41 @@
       }
     },
     "eslint-module-utils": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz",
-      "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz",
+      "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==",
       "dev": true,
       "requires": {
-        "debug": "^2.6.8",
+        "debug": "^3.2.7",
         "pkg-dir": "^2.0.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        }
+      }
+    },
+    "eslint-plugin-es": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz",
+      "integrity": "sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==",
+      "dev": true,
+      "requires": {
+        "eslint-utils": "^1.4.2",
+        "regexpp": "^2.0.1"
       }
     },
     "eslint-plugin-import": {
-      "version": "2.9.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz",
-      "integrity": "sha1-JgAu+/ylmJtyiKwEdQi9JPIXsWk=",
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz",
+      "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==",
       "dev": true,
       "requires": {
-        "builtin-modules": "^1.1.1",
         "contains-path": "^0.1.0",
         "debug": "^2.6.8",
         "doctrine": "1.5.0",
         "eslint-import-resolver-node": "^0.3.1",
-        "eslint-module-utils": "^2.1.1",
+        "eslint-module-utils": "^2.2.0",
         "has": "^1.0.1",
         "lodash": "^4.17.4",
         "minimatch": "^3.0.3",
-        "read-pkg-up": "^2.0.0"
+        "read-pkg-up": "^2.0.0",
+        "resolve": "^1.6.0"
       },
       "dependencies": {
         "debug": {
@@ -1274,65 +1247,78 @@
       }
     },
     "eslint-plugin-node": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz",
-      "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==",
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz",
+      "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==",
       "dev": true,
       "requires": {
-        "ignore": "^3.3.6",
+        "eslint-plugin-es": "^1.3.1",
+        "eslint-utils": "^1.3.1",
+        "ignore": "^4.0.2",
         "minimatch": "^3.0.4",
-        "resolve": "^1.3.3",
-        "semver": "^5.4.1"
+        "resolve": "^1.8.1",
+        "semver": "^5.5.0"
       }
     },
     "eslint-plugin-promise": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz",
-      "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz",
+      "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==",
       "dev": true
     },
     "eslint-plugin-react": {
-      "version": "7.7.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz",
-      "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==",
+      "version": "7.11.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz",
+      "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==",
       "dev": true,
       "requires": {
-        "doctrine": "^2.0.2",
-        "has": "^1.0.1",
+        "array-includes": "^3.0.3",
+        "doctrine": "^2.1.0",
+        "has": "^1.0.3",
         "jsx-ast-utils": "^2.0.1",
-        "prop-types": "^15.6.0"
+        "prop-types": "^15.6.2"
       }
     },
     "eslint-plugin-standard": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz",
-      "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz",
+      "integrity": "sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==",
       "dev": true
     },
     "eslint-scope": {
-      "version": "3.7.3",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
-      "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+      "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
       "dev": true,
       "requires": {
         "esrecurse": "^4.1.0",
         "estraverse": "^4.1.1"
       }
     },
+    "eslint-utils": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+      "dev": true,
+      "requires": {
+        "eslint-visitor-keys": "^1.1.0"
+      }
+    },
     "eslint-visitor-keys": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
-      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+      "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
       "dev": true
     },
     "espree": {
-      "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
-      "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz",
+      "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==",
       "dev": true,
       "requires": {
-        "acorn": "^5.5.0",
-        "acorn-jsx": "^3.0.0"
+        "acorn": "^6.0.2",
+        "acorn-jsx": "^5.0.0",
+        "eslint-visitor-keys": "^1.0.0"
       }
     },
     "esprima": {
@@ -1342,33 +1328,49 @@
       "dev": true
     },
     "esquery": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
-      "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+      "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
       "dev": true,
       "requires": {
-        "estraverse": "^4.0.0"
+        "estraverse": "^5.1.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
       }
     },
     "esrecurse": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
-      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
       "dev": true,
       "requires": {
-        "estraverse": "^4.1.0"
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
       }
     },
     "estraverse": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
-      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
       "dev": true
     },
     "esutils": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
-      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
       "dev": true
     },
     "etag": {
@@ -1377,38 +1379,38 @@
       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
     },
     "express": {
-      "version": "4.16.4",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
-      "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+      "version": "4.17.1",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+      "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
       "requires": {
-        "accepts": "~1.3.5",
+        "accepts": "~1.3.7",
         "array-flatten": "1.1.1",
-        "body-parser": "1.18.3",
-        "content-disposition": "0.5.2",
+        "body-parser": "1.19.0",
+        "content-disposition": "0.5.3",
         "content-type": "~1.0.4",
-        "cookie": "0.3.1",
+        "cookie": "0.4.0",
         "cookie-signature": "1.0.6",
         "debug": "2.6.9",
         "depd": "~1.1.2",
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
-        "finalhandler": "1.1.1",
+        "finalhandler": "~1.1.2",
         "fresh": "0.5.2",
         "merge-descriptors": "1.0.1",
         "methods": "~1.1.2",
         "on-finished": "~2.3.0",
-        "parseurl": "~1.3.2",
+        "parseurl": "~1.3.3",
         "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.4",
-        "qs": "6.5.2",
-        "range-parser": "~1.2.0",
+        "proxy-addr": "~2.0.5",
+        "qs": "6.7.0",
+        "range-parser": "~1.2.1",
         "safe-buffer": "5.1.2",
-        "send": "0.16.2",
-        "serve-static": "1.13.2",
-        "setprototypeof": "1.1.0",
-        "statuses": "~1.4.0",
-        "type-is": "~1.6.16",
+        "send": "0.17.1",
+        "serve-static": "1.14.1",
+        "setprototypeof": "1.1.1",
+        "statuses": "~1.5.0",
+        "type-is": "~1.6.18",
         "utils-merge": "1.0.1",
         "vary": "~1.1.2"
       },
@@ -1427,9 +1429,9 @@
           "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
         },
         "qs": {
-          "version": "6.5.2",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+          "version": "6.7.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
         }
       }
     },
@@ -1455,14 +1457,14 @@
       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
     },
     "fast-deep-equal": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
-      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
     "fast-json-stable-stringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
     },
     "fast-levenshtein": {
       "version": "2.0.6",
@@ -1471,14 +1473,14 @@
       "dev": true
     },
     "fast-safe-stringify": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
-      "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
+      "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
     },
     "fecha": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
-      "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz",
+      "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q=="
     },
     "figures": {
       "version": "2.0.0",
@@ -1500,16 +1502,16 @@
       }
     },
     "finalhandler": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
-      "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
       "requires": {
         "debug": "2.6.9",
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
         "on-finished": "~2.3.0",
-        "parseurl": "~1.3.2",
-        "statuses": "~1.4.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
         "unpipe": "~1.0.0"
       },
       "dependencies": {
@@ -1556,9 +1558,9 @@
       },
       "dependencies": {
         "glob": {
-          "version": "7.1.3",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-          "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+          "version": "7.1.7",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+          "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
           "dev": true,
           "requires": {
             "fs.realpath": "^1.0.0",
@@ -1580,19 +1582,23 @@
         }
       }
     },
+    "fn.name": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
+      "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
+    },
     "follow-redirects": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz",
-      "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=",
+      "version": "1.5.10",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+      "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
       "requires": {
-        "debug": "^2.2.0",
-        "stream-consume": "^0.1.0"
+        "debug": "=3.1.0"
       },
       "dependencies": {
         "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
           "requires": {
             "ms": "2.0.0"
           }
@@ -1610,9 +1616,9 @@
       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
     },
     "form-data": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
-      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
+      "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
       "requires": {
         "asynckit": "^0.4.0",
         "combined-stream": "^1.0.6",
@@ -1620,14 +1626,14 @@
       }
     },
     "formidable": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
-      "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
+      "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
     },
     "forwarded": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
-      "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
     },
     "fresh": {
       "version": "0.5.2",
@@ -1643,8 +1649,7 @@
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "dev": true
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
     },
     "functional-red-black-tree": {
       "version": "1.0.1",
@@ -1652,6 +1657,16 @@
       "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
       "dev": true
     },
+    "get-intrinsic": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+      "requires": {
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-symbols": "^1.0.1"
+      }
+    },
     "get-parameter-names": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/get-parameter-names/-/get-parameter-names-0.3.0.tgz",
@@ -1685,15 +1700,15 @@
       }
     },
     "globals": {
-      "version": "11.11.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz",
-      "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==",
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
       "dev": true
     },
     "graceful-fs": {
-      "version": "4.1.15",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
-      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+      "version": "4.2.6",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
+      "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==",
       "dev": true
     },
     "growl": {
@@ -1708,11 +1723,11 @@
       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
     },
     "har-validator": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
-      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
       "requires": {
-        "ajv": "^6.5.5",
+        "ajv": "^6.12.3",
         "har-schema": "^2.0.0"
       }
     },
@@ -1720,7 +1735,6 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "dev": true,
       "requires": {
         "function-bind": "^1.1.1"
       }
@@ -1734,6 +1748,12 @@
         "ansi-regex": "^2.0.0"
       }
     },
+    "has-bigints": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
+      "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
+      "dev": true
+    },
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -1741,10 +1761,9 @@
       "dev": true
     },
     "has-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
-      "dev": true
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+      "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
     },
     "hashring": {
       "version": "3.2.0",
@@ -1762,25 +1781,58 @@
       "dev": true
     },
     "hoek": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz",
-      "integrity": "sha512-6qhh/wahGYZHFSFw12tBbJw5fsAhhwrrG/y3Cs0YMTv2WzMnL0oLPnQJjv1QJvEfylRSOFuP+xCu+tdx0tD16Q=="
+      "version": "6.1.3",
+      "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+      "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
     },
     "hosted-git-info": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
-      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+      "version": "2.8.9",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
       "dev": true
     },
     "http-errors": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+      "version": "1.7.2",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+      "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
       "requires": {
         "depd": "~1.1.2",
         "inherits": "2.0.3",
-        "setprototypeof": "1.1.0",
-        "statuses": ">= 1.4.0 < 2"
+        "setprototypeof": "1.1.1",
+        "statuses": ">= 1.5.0 < 2",
+        "toidentifier": "1.0.0"
+      },
+      "dependencies": {
+        "inherits": {
+          "version": "2.0.3",
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+        }
+      }
+    },
+    "http-proxy-agent": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+      "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+      "requires": {
+        "@tootallnate/once": "1",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        }
       }
     },
     "http-signature": {
@@ -1793,89 +1845,42 @@
         "sshpk": "^1.7.0"
       }
     },
-    "iconv-lite": {
-      "version": "0.4.23",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
-      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+    "https-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
       "requires": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      }
-    },
-    "idtoken-verifier": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/idtoken-verifier/-/idtoken-verifier-1.2.0.tgz",
-      "integrity": "sha512-8jmmFHwdPz8L73zGNAXHHOV9yXNC+Z0TUBN5rafpoaFaLFltlIFr1JkQa3FYAETP23eSsulVw0sBiwrE8jqbUg==",
-      "requires": {
-        "base64-js": "^1.2.0",
-        "crypto-js": "^3.1.9-1",
-        "jsbn": "^0.1.0",
-        "superagent": "^3.8.2",
-        "url-join": "^1.1.0"
+        "agent-base": "6",
+        "debug": "4"
       },
       "dependencies": {
         "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "mime": {
-          "version": "1.6.0",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-          "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
+            "ms": "2.1.2"
           }
         },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        },
-        "superagent": {
-          "version": "3.8.3",
-          "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
-          "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
-          "requires": {
-            "component-emitter": "^1.2.0",
-            "cookiejar": "^2.1.0",
-            "debug": "^3.1.0",
-            "extend": "^3.0.0",
-            "form-data": "^2.3.1",
-            "formidable": "^1.2.0",
-            "methods": "^1.1.1",
-            "mime": "^1.4.1",
-            "qs": "^6.5.1",
-            "readable-stream": "^2.3.5"
-          }
-        },
-        "url-join": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
-          "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg="
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
         }
       }
     },
+    "iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      }
+    },
     "ignore": {
-      "version": "3.3.10",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
-      "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
       "dev": true
     },
     "imurmurhash": {
@@ -1894,52 +1899,75 @@
       }
     },
     "inherits": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "inquirer": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
-      "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
+      "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
       "dev": true,
       "requires": {
         "ansi-escapes": "^3.0.0",
         "chalk": "^2.0.0",
         "cli-cursor": "^2.1.0",
         "cli-width": "^2.0.0",
-        "external-editor": "^2.0.4",
+        "external-editor": "^2.1.0",
         "figures": "^2.0.0",
         "lodash": "^4.3.0",
         "mute-stream": "0.0.7",
         "run-async": "^2.2.0",
-        "rx-lite": "^4.0.8",
-        "rx-lite-aggregates": "^4.0.8",
+        "rxjs": "^5.5.2",
         "string-width": "^2.1.0",
         "strip-ansi": "^4.0.0",
         "through": "^2.3.6"
       }
     },
     "ipaddr.js": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
-      "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
     },
     "is-arrayish": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
       "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
     },
+    "is-bigint": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
+      "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
+      "dev": true
+    },
+    "is-boolean-object": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
+      "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2"
+      }
+    },
     "is-callable": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
+      "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
       "dev": true
     },
+    "is-core-module": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+      "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
     "is-date-object": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
+      "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
       "dev": true
     },
     "is-fullwidth-code-point": {
@@ -1948,19 +1976,26 @@
       "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
       "dev": true
     },
-    "is-promise": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
-      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+    "is-negative-zero": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
+      "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+      "dev": true
+    },
+    "is-number-object": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
+      "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
       "dev": true
     },
     "is-regex": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
-      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
+      "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
       "dev": true,
       "requires": {
-        "has": "^1.0.1"
+        "call-bind": "^1.0.2",
+        "has-symbols": "^1.0.2"
       }
     },
     "is-resolvable": {
@@ -1970,17 +2005,23 @@
       "dev": true
     },
     "is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+      "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
+    },
+    "is-string": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
+      "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
+      "dev": true
     },
     "is-symbol": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
-      "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
       "dev": true,
       "requires": {
-        "has-symbols": "^1.0.0"
+        "has-symbols": "^1.0.2"
       }
     },
     "is-typedarray": {
@@ -2013,24 +2054,32 @@
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
     "istanbul-lib-coverage": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz",
-      "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==",
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
       "dev": true
     },
     "istanbul-lib-instrument": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz",
-      "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==",
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
       "dev": true,
       "requires": {
-        "@babel/generator": "^7.0.0",
-        "@babel/parser": "^7.0.0",
-        "@babel/template": "^7.0.0",
-        "@babel/traverse": "^7.0.0",
-        "@babel/types": "^7.0.0",
-        "istanbul-lib-coverage": "^2.0.3",
-        "semver": "^5.5.0"
+        "@babel/generator": "^7.4.0",
+        "@babel/parser": "^7.4.3",
+        "@babel/template": "^7.4.0",
+        "@babel/traverse": "^7.4.3",
+        "@babel/types": "^7.4.0",
+        "istanbul-lib-coverage": "^2.0.5",
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
       }
     },
     "joi": {
@@ -2043,21 +2092,16 @@
         "topo": "3.x.x"
       }
     },
-    "js-cookie": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.0.tgz",
-      "integrity": "sha1-Gywnmm7s44ChIWi5JIUmWzWx7/s="
-    },
     "js-tokens": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
-      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
       "dev": true
     },
     "js-yaml": {
-      "version": "3.12.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz",
-      "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==",
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
       "dev": true,
       "requires": {
         "argparse": "^1.0.7",
@@ -2103,19 +2147,19 @@
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
     },
     "json5": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-      "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+      "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
       "requires": {
-        "minimist": "^1.2.0"
+        "minimist": "^1.2.5"
       }
     },
     "jsonwebtoken": {
-      "version": "8.5.0",
-      "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz",
-      "integrity": "sha512-IqEycp0znWHNA11TpYi77bVgyBO/pGESDh7Ajhas+u0ttkGkKYIIAjniL4Bw5+oVejVF+SYkaI7XKfwCCyeTuA==",
+      "version": "8.5.1",
+      "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+      "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
       "requires": {
-        "jws": "^3.2.1",
+        "jws": "^3.2.2",
         "lodash.includes": "^4.3.0",
         "lodash.isboolean": "^3.0.3",
         "lodash.isinteger": "^4.0.4",
@@ -2139,18 +2183,19 @@
       }
     },
     "jsx-ast-utils": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
-      "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz",
+      "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==",
       "dev": true,
       "requires": {
-        "array-includes": "^3.0.3"
+        "array-includes": "^3.1.1",
+        "object.assign": "^4.1.0"
       }
     },
     "jwa": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.3.0.tgz",
-      "integrity": "sha512-SxObIyzv9a6MYuZYaSN6DhSm9j3+qkokwvCB0/OTSV5ylPq1wUQiygZQcHT5Qlux0I5kmISx3J86TxKhuefItg==",
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+      "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
       "requires": {
         "buffer-equal-constant-time": "1.0.1",
         "ecdsa-sig-formatter": "1.0.11",
@@ -2158,71 +2203,65 @@
       }
     },
     "jwks-rsa": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.4.0.tgz",
-      "integrity": "sha512-6aUc+oTuqsLwIarfq3A0FqoD5LFSgveW5JO1uX2s0J8TJuOEcDc4NIMZAmVHO8tMHDw7CwOPzXF/9QhfOpOElA==",
-      "requires": {
-        "@types/express-jwt": "0.0.34",
-        "debug": "^2.2.0",
-        "limiter": "^1.1.0",
-        "lru-memoizer": "^1.6.0",
-        "ms": "^2.0.0",
-        "request": "^2.73.0"
+      "version": "1.12.3",
+      "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.3.tgz",
+      "integrity": "sha512-cFipFDeYYaO9FhhYJcZWX/IyZgc0+g316rcHnDpT2dNRNIE/lMOmWKKqp09TkJoYlNFzrEVODsR4GgXJMgWhnA==",
+      "requires": {
+        "@types/express-jwt": "0.0.42",
+        "axios": "^0.21.1",
+        "debug": "^4.1.0",
+        "http-proxy-agent": "^4.0.1",
+        "https-proxy-agent": "^5.0.0",
+        "jsonwebtoken": "^8.5.1",
+        "limiter": "^1.1.5",
+        "lru-memoizer": "^2.1.2",
+        "ms": "^2.1.2",
+        "proxy-from-env": "^1.1.0"
       },
       "dependencies": {
+        "axios": {
+          "version": "0.21.1",
+          "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
+          "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+          "requires": {
+            "follow-redirects": "^1.10.0"
+          }
+        },
         "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
           "requires": {
-            "ms": "2.0.0"
+            "ms": "2.1.2"
           },
           "dependencies": {
             "ms": {
-              "version": "2.0.0",
-              "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-              "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+              "version": "2.1.2",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+              "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
             }
           }
+        },
+        "follow-redirects": {
+          "version": "1.14.1",
+          "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
+          "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
         }
       }
     },
     "jws": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz",
-      "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==",
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+      "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
       "requires": {
-        "jwa": "^1.2.0",
+        "jwa": "^1.4.1",
         "safe-buffer": "^5.0.1"
       }
     },
     "kuler": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
-      "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
-      "requires": {
-        "colornames": "^1.1.1"
-      }
-    },
-    "le_node": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/le_node/-/le_node-1.8.0.tgz",
-      "integrity": "sha512-NXzjxBskZ4QawTNwlGdRG05jYU0LhV2nxxmP3x7sRMHyROV0jPdyyikO9at+uYrWX3VFt0Y/am11oKITedx0iw==",
-      "requires": {
-        "babel-runtime": "6.6.1",
-        "codependency": "0.1.4",
-        "json-stringify-safe": "5.0.1",
-        "lodash": "4.17.11",
-        "reconnect-core": "1.3.0",
-        "semver": "5.1.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.1.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz",
-          "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU="
-        }
-      }
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
+      "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
     },
     "levn": {
       "version": "0.3.0",
@@ -2235,9 +2274,9 @@
       }
     },
     "limiter": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz",
-      "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg=="
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
+      "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
     },
     "load-json-file": {
       "version": "2.0.0",
@@ -2261,15 +2300,15 @@
         "path-exists": "^3.0.0"
       }
     },
-    "lock": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/lock/-/lock-0.1.4.tgz",
-      "integrity": "sha1-/sfervF+fDoKVeHaBCgD4l2RdF0="
-    },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
     },
     "lodash.includes": {
       "version": "4.3.0",
@@ -2307,13 +2346,13 @@
       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
     },
     "logform": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz",
-      "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
+      "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==",
       "requires": {
         "colors": "^1.2.1",
         "fast-safe-stringify": "^2.0.4",
-        "fecha": "^2.3.3",
+        "fecha": "^4.2.0",
         "ms": "^2.1.1",
         "triple-beam": "^1.3.0"
       }
@@ -2342,14 +2381,12 @@
       }
     },
     "lru-memoizer": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-1.12.0.tgz",
-      "integrity": "sha1-7+ZXBsyKnMZT+A8NWm6jitlQ41I=",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz",
+      "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==",
       "requires": {
-        "lock": "~0.1.2",
-        "lodash": "^4.17.4",
-        "lru-cache": "~4.0.0",
-        "very-fast-args": "^1.1.0"
+        "lodash.clonedeep": "^4.5.0",
+        "lru-cache": "~4.0.0"
       }
     },
     "media-typer": {
@@ -2373,21 +2410,21 @@
       "integrity": "sha1-bMWtOGJByrjniv+WT4cCjuyS2sU="
     },
     "mime": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
-      "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w=="
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
     },
     "mime-db": {
-      "version": "1.38.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
-      "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
+      "version": "1.48.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
+      "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ=="
     },
     "mime-types": {
-      "version": "2.1.22",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
-      "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
+      "version": "2.1.31",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
+      "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
       "requires": {
-        "mime-db": "~1.38.0"
+        "mime-db": "1.48.0"
       }
     },
     "mimic-fn": {
@@ -2405,23 +2442,16 @@
       }
     },
     "minimist": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
     },
     "mkdirp": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
       "requires": {
-        "minimist": "0.0.8"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "0.0.8",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
-        }
+        "minimist": "^1.2.5"
       }
     },
     "mocha": {
@@ -2466,6 +2496,21 @@
             "path-is-absolute": "^1.0.0"
           }
         },
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "0.5.1",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+          "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+          "dev": true,
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -2474,16 +2519,22 @@
         }
       }
     },
+    "mocha-prepare": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/mocha-prepare/-/mocha-prepare-0.1.0.tgz",
+      "integrity": "sha1-VRMidoEiLkNJSB7k5GJHLzHGu4I=",
+      "dev": true
+    },
     "moment": {
-      "version": "2.24.0",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
-      "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
+      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
       "optional": true
     },
     "ms": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-      "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
     },
     "murmur-hash-js": {
       "version": "1.0.0",
@@ -2508,9 +2559,9 @@
       }
     },
     "nan": {
-      "version": "2.12.1",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
-      "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
+      "version": "2.14.2",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
+      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
       "optional": true
     },
     "natural-compare": {
@@ -2526,9 +2577,9 @@
       "optional": true
     },
     "negotiator": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
-      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+      "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
     },
     "nice-simple-logger": {
       "version": "1.0.1",
@@ -2538,6 +2589,12 @@
         "lodash": "^4.3.0"
       }
     },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
     "no-kafka": {
       "version": "3.4.3",
       "resolved": "https://registry.npmjs.org/no-kafka/-/no-kafka-3.4.3.tgz",
@@ -2553,6 +2610,43 @@
         "murmur-hash-js": "^1.0.0",
         "nice-simple-logger": "^1.0.1",
         "wrr-pool": "^1.0.3"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "4.17.11",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+          "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+        }
+      }
+    },
+    "nock": {
+      "version": "11.9.1",
+      "resolved": "https://registry.npmjs.org/nock/-/nock-11.9.1.tgz",
+      "integrity": "sha512-U5wPctaY4/ar2JJ5Jg4wJxlbBfayxgKbiAeGh+a1kk6Pwnc2ZEuKviLyDSG6t0uXl56q7AALIxoM6FJrBSsVXA==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.0",
+        "json-stringify-safe": "^5.0.1",
+        "lodash": "^4.17.13",
+        "mkdirp": "^0.5.0",
+        "propagate": "^2.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "dev": true,
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+          "dev": true
+        }
       }
     },
     "normalize-package-data": {
@@ -3612,12 +3706,29 @@
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
       "dev": true
     },
+    "object-inspect": {
+      "version": "1.10.3",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
+      "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw=="
+    },
     "object-keys": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
-      "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
       "dev": true
     },
+    "object.assign": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+      "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.0",
+        "define-properties": "^1.1.3",
+        "has-symbols": "^1.0.1",
+        "object-keys": "^1.1.1"
+      }
+    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -3635,9 +3746,12 @@
       }
     },
     "one-time": {
-      "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
-      "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
+      "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
+      "requires": {
+        "fn.name": "1.x.x"
+      }
     },
     "onetime": {
       "version": "2.0.1",
@@ -3649,17 +3763,17 @@
       }
     },
     "optionator": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
-      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
       "dev": true,
       "requires": {
         "deep-is": "~0.1.3",
-        "fast-levenshtein": "~2.0.4",
+        "fast-levenshtein": "~2.0.6",
         "levn": "~0.3.0",
         "prelude-ls": "~1.1.2",
         "type-check": "~0.3.2",
-        "wordwrap": "~1.0.0"
+        "word-wrap": "~1.2.3"
       }
     },
     "os-tmpdir": {
@@ -3702,9 +3816,9 @@
       }
     },
     "parseurl": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
-      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
     },
     "path-exists": {
       "version": "3.0.0",
@@ -3723,10 +3837,16 @@
       "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
       "dev": true
     },
+    "path-key": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+      "dev": true
+    },
     "path-parse": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
       "dev": true
     },
     "path-to-regexp": {
@@ -3832,9 +3952,9 @@
       "dev": true
     },
     "process-nextick-args": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
-      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
     "progress": {
       "version": "2.0.3",
@@ -3853,29 +3973,40 @@
         "react-is": "^16.8.1"
       }
     },
+    "propagate": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
+      "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
+      "dev": true
+    },
     "protocol-buffers-schema": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz",
-      "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w=="
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.5.1.tgz",
+      "integrity": "sha512-YVCvdhxWNDP8/nJDyXLuM+UFsuPk4+1PB7WGPVDzm3HTHbzFLxQYeW2iZpS4mmnXrQJGBzt230t/BbEb7PrQaw=="
     },
     "proxy-addr": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
-      "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
       "requires": {
-        "forwarded": "~0.1.2",
-        "ipaddr.js": "1.8.0"
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
       }
     },
+    "proxy-from-env": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+    },
     "pseudomap": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
       "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
     },
     "psl": {
-      "version": "1.1.31",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
-      "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
     },
     "punycode": {
       "version": "2.1.1",
@@ -3883,30 +4014,64 @@
       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
     },
     "qs": {
-      "version": "6.6.0",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz",
-      "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA=="
+      "version": "6.10.1",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+      "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+      "requires": {
+        "side-channel": "^1.0.4"
+      }
+    },
+    "queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true
+    },
+    "r7insight_node": {
+      "version": "1.8.4",
+      "resolved": "https://registry.npmjs.org/r7insight_node/-/r7insight_node-1.8.4.tgz",
+      "integrity": "sha512-6cQrzLkaOxdv/SRFXWRJjgFr8a3nXUOT/4IMFuBv+mWzBnu5DJl+HzONAsWYvclrlZnvfa54PaIPqPuPRSlbrQ==",
+      "requires": {
+        "babel-runtime": "6.6.1",
+        "codependency": "0.1.4",
+        "json-stringify-safe": "5.0.1",
+        "lodash": "4.17.15",
+        "reconnect-core": "1.3.0",
+        "semver": "5.1.0"
+      },
+      "dependencies": {
+        "lodash": {
+          "version": "4.17.15",
+          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+        },
+        "semver": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz",
+          "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU="
+        }
+      }
     },
     "range-parser": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
-      "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
     },
     "raw-body": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
-      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+      "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
       "requires": {
-        "bytes": "3.0.0",
-        "http-errors": "1.6.3",
-        "iconv-lite": "0.4.23",
+        "bytes": "3.1.0",
+        "http-errors": "1.7.2",
+        "iconv-lite": "0.4.24",
         "unpipe": "1.0.0"
       }
     },
     "react-is": {
-      "version": "16.8.3",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
-      "integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA==",
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
       "dev": true
     },
     "read-pkg": {
@@ -3931,13 +4096,17 @@
       }
     },
     "readable-stream": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
-      "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
       "requires": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
       }
     },
     "reconnect-core": {
@@ -3948,10 +4117,16 @@
         "backoff": "~2.5.0"
       }
     },
+    "regexpp": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+      "dev": true
+    },
     "request": {
-      "version": "2.88.0",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
-      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+      "version": "2.88.2",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+      "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
       "requires": {
         "aws-sign2": "~0.7.0",
         "aws4": "^1.8.0",
@@ -3960,7 +4135,7 @@
         "extend": "~3.0.2",
         "forever-agent": "~0.6.1",
         "form-data": "~2.3.2",
-        "har-validator": "~5.1.0",
+        "har-validator": "~5.1.3",
         "http-signature": "~1.2.0",
         "is-typedarray": "~1.0.0",
         "isstream": "~0.1.2",
@@ -3970,11 +4145,21 @@
         "performance-now": "^2.1.0",
         "qs": "~6.5.2",
         "safe-buffer": "^5.1.2",
-        "tough-cookie": "~2.4.3",
+        "tough-cookie": "~2.5.0",
         "tunnel-agent": "^0.6.0",
         "uuid": "^3.3.2"
       },
       "dependencies": {
+        "form-data": {
+          "version": "2.3.3",
+          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+          "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+          "requires": {
+            "asynckit": "^0.4.0",
+            "combined-stream": "^1.0.6",
+            "mime-types": "^2.1.12"
+          }
+        },
         "qs": {
           "version": "6.5.2",
           "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
@@ -3993,11 +4178,12 @@
       }
     },
     "resolve": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
-      "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
       "dev": true,
       "requires": {
+        "is-core-module": "^2.2.0",
         "path-parse": "^1.0.6"
       }
     },
@@ -4027,33 +4213,27 @@
       }
     },
     "run-async": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
-      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+      "dev": true
+    },
+    "run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
       "dev": true,
       "requires": {
-        "is-promise": "^2.1.0"
+        "queue-microtask": "^1.2.2"
       }
     },
-    "run-parallel": {
-      "version": "1.1.9",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
-      "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
-      "dev": true
-    },
-    "rx-lite": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
-      "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
-      "dev": true
-    },
-    "rx-lite-aggregates": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
-      "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+    "rxjs": {
+      "version": "5.5.12",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
+      "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
       "dev": true,
       "requires": {
-        "rx-lite": "*"
+        "symbol-observable": "1.0.1"
       }
     },
     "safe-buffer": {
@@ -4073,14 +4253,14 @@
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "semver": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
-      "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
     },
     "send": {
-      "version": "0.16.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
-      "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+      "version": "0.17.1",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+      "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
       "requires": {
         "debug": "2.6.9",
         "depd": "~1.1.2",
@@ -4089,12 +4269,12 @@
         "escape-html": "~1.0.3",
         "etag": "~1.8.1",
         "fresh": "0.5.2",
-        "http-errors": "~1.6.2",
-        "mime": "1.4.1",
-        "ms": "2.0.0",
+        "http-errors": "~1.7.2",
+        "mime": "1.6.0",
+        "ms": "2.1.1",
         "on-finished": "~2.3.0",
-        "range-parser": "~1.2.0",
-        "statuses": "~1.4.0"
+        "range-parser": "~1.2.1",
+        "statuses": "~1.5.0"
       },
       "dependencies": {
         "debug": {
@@ -4103,35 +4283,37 @@
           "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
           "requires": {
             "ms": "2.0.0"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+              "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+            }
           }
         },
-        "mime": {
-          "version": "1.4.1",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
-          "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
-        },
         "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
         }
       }
     },
     "serve-static": {
-      "version": "1.13.2",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
-      "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+      "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
       "requires": {
         "encodeurl": "~1.0.2",
         "escape-html": "~1.0.3",
-        "parseurl": "~1.3.2",
-        "send": "0.16.2"
+        "parseurl": "~1.3.3",
+        "send": "0.17.1"
       }
     },
     "setprototypeof": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+      "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
     },
     "shebang-command": {
       "version": "1.2.0",
@@ -4197,15 +4379,25 @@
       }
     },
     "should-util": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz",
-      "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz",
+      "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==",
       "dev": true
     },
+    "side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "requires": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      }
+    },
     "signal-exit": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
-      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
       "dev": true
     },
     "simple-lru-cache": {
@@ -4237,9 +4429,9 @@
       "dev": true
     },
     "spdx-correct": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
-      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+      "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
       "dev": true,
       "requires": {
         "spdx-expression-parse": "^3.0.0",
@@ -4247,15 +4439,15 @@
       }
     },
     "spdx-exceptions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
-      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
       "dev": true
     },
     "spdx-expression-parse": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
-      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
       "dev": true,
       "requires": {
         "spdx-exceptions": "^2.1.0",
@@ -4263,9 +4455,9 @@
       }
     },
     "spdx-license-ids": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz",
-      "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==",
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz",
+      "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==",
       "dev": true
     },
     "sprintf-js": {
@@ -4296,26 +4488,26 @@
       "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
     },
     "standard": {
-      "version": "11.0.1",
-      "resolved": "https://registry.npmjs.org/standard/-/standard-11.0.1.tgz",
-      "integrity": "sha512-nu0jAcHiSc8H+gJCXeiziMVZNDYi8MuqrYJKxTgjP4xKXZMKm311boqQIzDrYI/ktosltxt2CbDjYQs9ANC8IA==",
+      "version": "12.0.1",
+      "resolved": "https://registry.npmjs.org/standard/-/standard-12.0.1.tgz",
+      "integrity": "sha512-UqdHjh87OG2gUrNCSM4QRLF5n9h3TFPwrCNyVlkqu31Hej0L/rc8hzKqVvkb2W3x0WMq7PzZdkLfEcBhVOR6lg==",
       "dev": true,
       "requires": {
-        "eslint": "~4.18.0",
-        "eslint-config-standard": "11.0.0",
-        "eslint-config-standard-jsx": "5.0.0",
-        "eslint-plugin-import": "~2.9.0",
-        "eslint-plugin-node": "~6.0.0",
-        "eslint-plugin-promise": "~3.7.0",
-        "eslint-plugin-react": "~7.7.0",
-        "eslint-plugin-standard": "~3.0.1",
-        "standard-engine": "~8.0.0"
+        "eslint": "~5.4.0",
+        "eslint-config-standard": "12.0.0",
+        "eslint-config-standard-jsx": "6.0.2",
+        "eslint-plugin-import": "~2.14.0",
+        "eslint-plugin-node": "~7.0.1",
+        "eslint-plugin-promise": "~4.0.0",
+        "eslint-plugin-react": "~7.11.1",
+        "eslint-plugin-standard": "~4.0.0",
+        "standard-engine": "~9.0.0"
       }
     },
     "standard-engine": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-8.0.1.tgz",
-      "integrity": "sha512-LA531C3+nljom/XRvdW/hGPXwmilRkaRkENhO3FAGF1Vtq/WtCXzgmnc5S6vUHHsgv534MRy02C1ikMwZXC+tw==",
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-9.0.0.tgz",
+      "integrity": "sha512-ZfNfCWZ2Xq67VNvKMPiVMKHnMdvxYzvZkf1AH8/cw2NLDBm5LRsxMqvEJpsjLI/dUosZ3Z1d6JlHDp5rAvvk2w==",
       "dev": true,
       "requires": {
         "deglob": "^2.1.0",
@@ -4325,14 +4517,9 @@
       }
     },
     "statuses": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
-      "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
-    },
-    "stream-consume": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz",
-      "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg=="
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
     },
     "string-width": {
       "version": "2.1.1",
@@ -4344,10 +4531,30 @@
         "strip-ansi": "^4.0.0"
       }
     },
+    "string.prototype.trimend": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
+      "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3"
+      }
+    },
+    "string.prototype.trimstart": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
+      "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3"
+      }
+    },
     "string_decoder": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
-      "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
       "requires": {
         "safe-buffer": "~5.1.0"
       }
@@ -4395,6 +4602,36 @@
         "mime": "^2.4.0",
         "qs": "^6.6.0",
         "readable-stream": "^3.0.6"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "requires": {
+            "ms": "2.1.2"
+          }
+        },
+        "mime": {
+          "version": "2.5.2",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
+          "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg=="
+        },
+        "ms": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        },
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
       }
     },
     "supports-color": {
@@ -4406,59 +4643,59 @@
         "has-flag": "^3.0.0"
       }
     },
+    "symbol-observable": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
+      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
+      "dev": true
+    },
     "table": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
-      "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz",
+      "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==",
       "dev": true,
       "requires": {
-        "ajv": "^5.2.3",
-        "ajv-keywords": "^2.1.0",
+        "ajv": "^6.0.1",
+        "ajv-keywords": "^3.0.0",
         "chalk": "^2.1.0",
         "lodash": "^4.17.4",
         "slice-ansi": "1.0.0",
         "string-width": "^2.1.1"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "5.5.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-          "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-          "dev": true,
-          "requires": {
-            "co": "^4.6.0",
-            "fast-deep-equal": "^1.0.0",
-            "fast-json-stable-stringify": "^2.0.0",
-            "json-schema-traverse": "^0.3.0"
-          }
-        },
-        "fast-deep-equal": {
-          "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-          "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-          "dev": true
-        },
-        "json-schema-traverse": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-          "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-          "dev": true
-        }
       }
     },
     "tc-core-library-js": {
-      "version": "github:appirio-tech/tc-core-library-js#d16413db30b1eed21c0cf426e185bedb2329ddab",
-      "from": "github:appirio-tech/tc-core-library-js#v2.6",
+      "version": "github:appirio-tech/tc-core-library-js#2d87a80f9d00a03a4f105ca423e66de42246e71f",
+      "from": "github:appirio-tech/tc-core-library-js#v2.6.7",
       "requires": {
-        "auth0-js": "^9.4.2",
-        "axios": "^0.12.0",
+        "axios": "^0.19.0",
         "bunyan": "^1.8.12",
-        "jsonwebtoken": "^8.3.0",
-        "jwks-rsa": "^1.3.0",
-        "le_node": "^1.3.1",
-        "lodash": "^4.17.10",
+        "jsonwebtoken": "^8.5.1",
+        "jwks-rsa": "^1.6.0",
+        "lodash": "^4.17.15",
         "millisecond": "^0.1.2",
+        "r7insight_node": "^2.1.0",
         "request": "^2.88.0"
+      },
+      "dependencies": {
+        "codependency": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/codependency/-/codependency-2.1.0.tgz",
+          "integrity": "sha512-JIdmYkE8Z6jwH1OUf4a5H5jk9YShPQkaYPUAiN+ktyChmPP77LGbeKrxWGPqdCnpTmt0hRIn8TXBVu01U3HDhg==",
+          "requires": {
+            "semver": "^5.3.0"
+          }
+        },
+        "r7insight_node": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/r7insight_node/-/r7insight_node-2.1.1.tgz",
+          "integrity": "sha512-xx0kgFxSHWY9aG1109uv4w2b+JLwHseSowOWo1bzCTDBpUk3er2rZdtQ90mAjUYbkh6Hus9DAwWvmHsX5pHaIQ==",
+          "requires": {
+            "codependency": "^2.1.0",
+            "json-stringify-safe": "^5.0.1",
+            "lodash": "^4.17.15",
+            "reconnect-core": "^1.3.0"
+          }
+        }
       }
     },
     "text-hex": {
@@ -4493,6 +4730,11 @@
       "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
       "dev": true
     },
+    "toidentifier": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+      "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+    },
     "topcoder-healthcheck-dropin": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/topcoder-healthcheck-dropin/-/topcoder-healthcheck-dropin-1.0.3.tgz",
@@ -4510,27 +4752,14 @@
       }
     },
     "tough-cookie": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
-      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+      "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
       "requires": {
-        "psl": "^1.1.24",
-        "punycode": "^1.4.1"
-      },
-      "dependencies": {
-        "punycode": {
-          "version": "1.4.1",
-          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
-        }
+        "psl": "^1.1.28",
+        "punycode": "^2.1.1"
       }
     },
-    "trim-right": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
-      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
-      "dev": true
-    },
     "triple-beam": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
@@ -4559,19 +4788,25 @@
       }
     },
     "type-is": {
-      "version": "1.6.16",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
-      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
       "requires": {
         "media-typer": "0.3.0",
-        "mime-types": "~2.1.18"
+        "mime-types": "~2.1.24"
       }
     },
-    "typedarray": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
-      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
-      "dev": true
+    "unbox-primitive": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
+      "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1",
+        "has-bigints": "^1.0.1",
+        "has-symbols": "^1.0.2",
+        "which-boxed-primitive": "^1.0.2"
+      }
     },
     "uniq": {
       "version": "1.0.1",
@@ -4585,18 +4820,13 @@
       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
     },
     "uri-js": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
-      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
       "requires": {
         "punycode": "^2.1.0"
       }
     },
-    "url-join": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz",
-      "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo="
-    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -4608,9 +4838,9 @@
       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
     },
     "uuid": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
     },
     "validate-npm-package-license": {
       "version": "3.0.4",
@@ -4637,11 +4867,6 @@
         "extsprintf": "^1.2.0"
       }
     },
-    "very-fast-args": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/very-fast-args/-/very-fast-args-1.1.0.tgz",
-      "integrity": "sha1-4W0dH6+KbllqJGQh/ZCneWPQs5Y="
-    },
     "which": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -4651,64 +4876,60 @@
         "isexe": "^2.0.0"
       }
     },
-    "winchan": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/winchan/-/winchan-0.2.1.tgz",
-      "integrity": "sha512-QrG9q+ObfmZBxScv0HSCqFm/owcgyR5Sgpiy1NlCZPpFXhbsmNHhTiLWoogItdBUi0fnU7Io/5ABEqRta5/6Dw=="
+    "which-boxed-primitive": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+      "dev": true,
+      "requires": {
+        "is-bigint": "^1.0.1",
+        "is-boolean-object": "^1.1.0",
+        "is-number-object": "^1.0.4",
+        "is-string": "^1.0.5",
+        "is-symbol": "^1.0.3"
+      }
     },
     "winston": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz",
-      "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==",
-      "requires": {
-        "async": "^2.6.1",
-        "diagnostics": "^1.1.1",
-        "is-stream": "^1.1.0",
-        "logform": "^2.1.1",
-        "one-time": "0.0.4",
-        "readable-stream": "^3.1.1",
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz",
+      "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==",
+      "requires": {
+        "@dabh/diagnostics": "^2.0.2",
+        "async": "^3.1.0",
+        "is-stream": "^2.0.0",
+        "logform": "^2.2.0",
+        "one-time": "^1.0.0",
+        "readable-stream": "^3.4.0",
         "stack-trace": "0.0.x",
         "triple-beam": "^1.3.0",
-        "winston-transport": "^4.3.0"
-      }
-    },
-    "winston-transport": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz",
-      "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==",
-      "requires": {
-        "readable-stream": "^2.3.6",
-        "triple-beam": "^1.2.0"
+        "winston-transport": "^4.4.0"
       },
       "dependencies": {
         "readable-stream": {
-          "version": "2.3.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
           "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "requires": {
-            "safe-buffer": "~5.1.0"
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
           }
         }
       }
     },
-    "wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+    "winston-transport": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz",
+      "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==",
+      "requires": {
+        "readable-stream": "^2.3.7",
+        "triple-beam": "^1.2.0"
+      }
+    },
+    "word-wrap": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
       "dev": true
     },
     "wrappy": {
@@ -4734,9 +4955,9 @@
       }
     },
     "xtend": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
-      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
       "dev": true
     },
     "yallist": {
diff --git a/package.json b/package.json
index 839b864..71ce64d 100644
--- a/package.json
+++ b/package.json
@@ -7,26 +7,29 @@
     "start": "node src/app.js",
     "lint": "standard",
     "lint:fix": "standard --fix",
-    "test": "nyc --reporter=html --reporter=text mocha test/unit/test.js --timeout 20000 --exit",
-    "e2e": "nyc --reporter=html --reporter=text mocha test/e2e/test.js --timeout 20000 --exit"
+    "test": "nyc --reporter=html --reporter=text mocha test/unit/*.test.js --require test/common/prepare.js --timeout 20000 --exit",
+    "e2e": "nyc --reporter=html --reporter=text mocha test/e2e/*.test.js --require test/common/prepare.js --timeout 20000 --exit"
   },
   "author": "TCSCODER",
   "license": "none",
   "devDependencies": {
     "mocha": "^5.2.0",
+    "mocha-prepare": "^0.1.0",
+    "nock": "^11.3.5",
     "nyc": "^13.3.0",
     "should": "^13.2.3",
-    "standard": "^11.0.1"
+    "standard": "^12.0.1"
   },
   "dependencies": {
+    "@topcoder-platform/topcoder-submission-api-wrapper": "^1.1.0",
     "bluebird": "^3.5.3",
     "config": "^3.0.1",
     "get-parameter-names": "^0.3.0",
     "joi": "^14.3.1",
-    "lodash": "^4.17.11",
+    "lodash": "^4.17.20",
     "no-kafka": "^3.4.3",
     "superagent": "^4.1.0",
-    "tc-core-library-js": "appirio-tech/tc-core-library-js.git#v2.6",
+    "tc-core-library-js": "appirio-tech/tc-core-library-js.git#v2.6.7",
     "topcoder-healthcheck-dropin": "^1.0.2",
     "winston": "^3.2.1"
   },
@@ -41,8 +44,8 @@
   "nyc": {
     "exclude": [
       "test/common/*.js",
-      "test/unit/test.js",
-      "test/e2e/test.js"
+      "test/unit/*.js",
+      "test/e2e/*.js"
     ]
   }
 }
diff --git a/src/app.js b/src/app.js
index bbc64f5..6d879f3 100644
--- a/src/app.js
+++ b/src/app.js
@@ -8,13 +8,17 @@ const Kafka = require('no-kafka')
 const healthcheck = require('topcoder-healthcheck-dropin')
 const logger = require('./common/logger')
 const helper = require('./common/helper')
-const ProcessorService = require('./services/ProcessorService')
+const ReviewProcessorService = require('./services/ReviewProcessorService')
+const SubmissionProcessorService = require('./services/SubmissionProcessorService')
 
 // Start kafka consumer
 logger.info('Starting kafka consumer')
-// create consumer
 
-const consumer = new Kafka.GroupConsumer(helper.getKafkaOptions())
+// create consumer
+let consumer
+if (process.env.NODE_ENV !== 'test') {
+  consumer = new Kafka.GroupConsumer(helper.getKafkaOptions())
+}
 
 /*
  * Data handler linked with Kafka consumer
@@ -39,18 +43,29 @@ const dataHandler = (messageSet, topic, partition) => Promise.each(messageSet, a
     return
   }
 
+  console.log(topic, config.AGGREGATE_SUBMISSION_TOPIC, messageJSON.payload.originalTopic, config.CREATE_SUBMISSION_TOPIC)
+  console.log(topic === config.AGGREGATE_SUBMISSION_TOPIC, messageJSON.payload.originalTopic === config.CREATE_SUBMISSION_TOPIC)
+
   return (async () => {
-    if (topic === config.OR_REVIEW_TOPIC) {
-      await ProcessorService.process(messageJSON)
+    if (topic === config.REVIEW_TOPIC) {
+      await ReviewProcessorService.processReview(messageJSON)
+    } else if (topic === config.AGGREGATE_SUBMISSION_TOPIC &&
+      messageJSON.payload.originalTopic === config.CREATE_SUBMISSION_TOPIC) {
+      await SubmissionProcessorService.processSubmission(messageJSON)
+    } else if (topic === config.AGGREGATE_SUBMISSION_TOPIC) {
+      logger.info(`Ignoring topic ${topic} since the original topic is not ${config.CREATE_SUBMISSION_TOPIC}`)
     } else {
       throw new Error(`Invalid topic: ${topic}`)
     }
-    logger.debug('Successfully processed message')
   })()
-  // commit offset regardless of errors
-    .then(() => {})
+    .then(() => { logger.debug('Successfully processed message') })
     .catch((err) => { logger.logFullError(err) })
-    .finally(() => consumer.commitOffset({ topic, partition, offset: m.offset }))
+    // commit offset regardless of errors
+    .finally(() => {
+      if (consumer) {
+        consumer.commitOffset({ topic, partition, offset: m.offset })
+      }
+    })
 })
 
 // check if there is kafka connection alive
@@ -66,23 +81,25 @@ function check () {
   return connected
 }
 
-const topics = [config.OR_REVIEW_TOPIC]
+if (consumer) {
+  const topics = [config.REVIEW_TOPIC, config.AGGREGATE_SUBMISSION_TOPIC]
 
-consumer
-  .init([{
-    subscriptions: topics,
-    handler: dataHandler
-  }])
-  // consume configured topics
-  .then(() => {
-    logger.info('Initialized.......')
-    healthcheck.init([check])
-    logger.info('Adding topics successfully.......')
-    logger.info(topics)
-    logger.info('Kick Start.......')
-  })
-  .catch((err) => logger.error(err))
+  consumer
+    .init([{
+      subscriptions: topics,
+      handler: dataHandler
+    }])
+    // consume configured topics
+    .then(() => {
+      logger.info('Initialized.......')
+      healthcheck.init([check])
+      logger.info('Adding topics successfully.......')
+      logger.info(topics)
+      logger.info('Kick Start.......')
+    })
+    .catch((err) => logger.error(err))
+}
 
 if (process.env.NODE_ENV === 'test') {
-  module.exports = consumer
+  module.exports = dataHandler
 }
diff --git a/src/common/helper.js b/src/common/helper.js
index f10aca4..b378b1c 100644
--- a/src/common/helper.js
+++ b/src/common/helper.js
@@ -45,52 +45,20 @@ async function getRequest (url, query, m2mToken) {
 }
 
 /**
- * Uses superagent to proxy post request
- * @param {String} url the url
- * @param {Object} body the JSON object body
- * @param {String} m2mToken the M2M token
- * @returns {Object} the response
- */
-async function postRequest (url, body, m2mToken) {
-  await request
-    .post(url)
-    .send(body)
-    .set('Authorization', `Bearer ${m2mToken}`)
-    .set('Content-Type', 'application/json')
-    .set('Accept', 'application/json')
-}
-
-/**
- * Uses superagent to proxy put request
- * @param {String} url the url
- * @param {Object} body the JSON object body
- * @param {String} m2mToken the M2M token
- * @returns {Object} the response
- */
-async function putRequest (url, body, m2mToken) {
-  await request
-    .put(url)
-    .send(body)
-    .set('Authorization', `Bearer ${m2mToken}`)
-    .set('Content-Type', 'application/json')
-    .set('Accept', 'application/json')
-}
-
-/**
- * Fetch all resources.
- * @param {String} url the url
+ * Fetch all resources using submission api wrapper client
+ * @param {Object} client the submission api wrapper client
+ * @param {String} methodName the wrapper method name
  * @param {Object} query the query object
- * @param {String} m2mToken the M2M token
  * @returns {Object} the response
  */
-async function fetchAll (url, query, m2mToken) {
-  const res = await getRequest(url, query, m2mToken)
+async function fetchAll (client, methodName, query) {
+  const res = await client[methodName](query)
   let result = res.body
   const totalPage = Number(res.header['x-total-pages'])
   if (totalPage > 1) {
     const requests = []
     for (let i = 2; i <= totalPage; i++) {
-      requests.push(getRequest(url, _.assign({ page: i }, query), m2mToken))
+      requests.push(client[methodName](_.assign({ page: i }, query)))
     }
     const extraRes = await Promise.all(requests)
     result = _.reduce(extraRes, (ret, e) => ret.concat(e.body), result)
@@ -102,7 +70,5 @@ module.exports = {
   getKafkaOptions,
   getM2Mtoken,
   getRequest,
-  postRequest,
-  putRequest,
   fetchAll
 }
diff --git a/src/services/ProcessorService.js b/src/services/ReviewProcessorService.js
similarity index 63%
rename from src/services/ProcessorService.js
rename to src/services/ReviewProcessorService.js
index 9604a9d..eb9b6e9 100644
--- a/src/services/ProcessorService.js
+++ b/src/services/ReviewProcessorService.js
@@ -1,5 +1,5 @@
 /**
- * Processor Service
+ * Review Processor Service
  */
 
 const _ = require('lodash')
@@ -7,34 +7,37 @@ const joi = require('joi')
 const config = require('config')
 const logger = require('../common/logger')
 const helper = require('../common/helper')
+const submissionApi = require('@topcoder-platform/topcoder-submission-api-wrapper')
+const submissionApiM2MClient = submissionApi(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'TOKEN_CACHE_TIME', 'AUTH0_CLIENT_ID', 'AUTH0_CLIENT_SECRET', 'SUBMISSION_API_URL', 'AUTH0_PROXY_SERVER_URL']))
 
 /**
  * Process create and update review message
  * @param {Object} message the kafka message
  */
-async function process (message) {
+async function processReview (message) {
   const eventType = _.get(message, 'payload.eventType')
   if (eventType === 'CREATE' || eventType === 'UPDATE') {
-    const m2mToken = await helper.getM2Mtoken()
     const { payload } = message
 
     // get submission id via legacy id
-    const res = await helper.getRequest(config.SUBMISSION_API_URL,
-      { legacySubmissionId: payload.submissionId }, m2mToken)
+    logger.debug('Get submission')
+    const res = await submissionApiM2MClient.searchSubmissions({ legacySubmissionId: payload.submissionId })
     const [submission] = res.body
     if (_.isUndefined(submission)) {
       throw new Error(`Incorrect submission id ${payload.submissionId}`)
     }
+    logger.debug(`Submission id: ${submission.id}`)
 
     // get review type UUID
+    logger.debug('Get review type')
     const typeName = config.REVIEW_TYPES[payload.reviewTypeId]
-    const list = await helper.fetchAll(config.REVIEW_TYPE_API_URL,
-      { name: typeName, isActive: true, perPage: 100 }, m2mToken)
+    const list = await helper.fetchAll(submissionApiM2MClient, 'searchReviewTypes', { name: typeName, isActive: true, perPage: 100 })
     const reviewType = _.reduce(list,
       (result, e) => e.name.toLowerCase() === typeName.toLowerCase() ? e : result, undefined)
     if (_.isUndefined(reviewType)) {
       throw new Error(`Incorrect review type id ${payload.reviewTypeId}`)
     }
+    logger.debug(`Review type id: ${reviewType.id}`)
 
     // Use metadata to store legacy review id
     const body = {
@@ -46,29 +49,45 @@ async function process (message) {
     }
 
     if (eventType === 'CREATE') {
-      await helper.postRequest(config.REVIEW_API_URL, body, m2mToken)
+      logger.debug('Create review')
+      await submissionApiM2MClient.createReview(body)
     } else {
       // retrieve review
-      let res = await helper.getRequest(config.REVIEW_API_URL,
+      logger.debug('Get review')
+      let res = await submissionApiM2MClient.searchReviews(
         {
           submissionId: submission.id,
           reviewerId: payload.reviewerId,
           scoreCardId: payload.scorecardId
-        },
-        m2mToken)
-      const [review] = res.body
+        }
+      )
+      const reviews = res.body || []
+      // find latest review
+      let review
+      if (reviews.length > 0) {
+        review = reviews[0]
+      }
+      for (let i = 1; i < reviews.length; i += 1) {
+        if (new Date(reviews[i].created) > new Date(review.created)) {
+          review = reviews[i]
+        }
+      }
       if (_.isUndefined(review)) {
         throw new Error(`Review doesn't exist under criteria ${_.pick(payload, ['submissionId', 'reviewerId', 'scorecardId'])}`)
       }
 
-      await helper.putRequest(`${config.REVIEW_API_URL}/${review.id}`, body, m2mToken)
+      logger.debug(`Review id: ${review.id}`)
+
+      // update review
+      logger.debug('Update review')
+      await submissionApiM2MClient.updateReview(review.id, body)
     }
   } else {
     throw new Error(`Invalid or not supported eventType: ${eventType}`)
   }
 }
 
-process.schema = {
+processReview.schema = {
   message: joi.object().keys({
     topic: joi.string().required(),
     originator: joi.string().required(),
@@ -92,7 +111,7 @@ process.schema = {
 }
 
 module.exports = {
-  process
+  processReview
 }
 
 logger.buildService(module.exports)
diff --git a/src/services/SubmissionProcessorService.js b/src/services/SubmissionProcessorService.js
new file mode 100644
index 0000000..7f933da
--- /dev/null
+++ b/src/services/SubmissionProcessorService.js
@@ -0,0 +1,182 @@
+/**
+ * Submission Processor Service
+ */
+
+const _ = require('lodash')
+const joi = require('joi')
+const config = require('config')
+const Kafka = require('no-kafka')
+const logger = require('../common/logger')
+const helper = require('../common/helper')
+
+// global Kafka producer to send message
+let producer = null
+
+/**
+ * Extract file name from URL.
+ * @param {String} url the url
+ * @returns {String} the extracted file name, or null if none is found
+ */
+function extractFileNameFromUrl (url) {
+  if (!url) {
+    return null
+  }
+  let index = url.lastIndexOf('/')
+  if (index < 0) {
+    return null
+  }
+  let s = url.substring(index + 1)
+  // remove query parameters if any
+  index = s.indexOf('?')
+  if (index >= 0) {
+    s = s.substring(0, index)
+  }
+  // remove state part (#) if any
+  index = s.indexOf('#')
+  if (index >= 0) {
+    s = s.substring(0, index)
+  }
+  return s
+}
+
+/**
+ * Generate score system message.
+ * @param {Object} message the kafka message
+ * @param {Object} scoreSystem the score system
+ * @returns {Object} the generated message for the score system
+ */
+function generateScoreSystemMessage (message, scoreSystem) {
+  if (scoreSystem.topic === 'avscan.action.scan') {
+    return {
+      topic: scoreSystem.topic,
+      originator: 'tc-scorecard-processor',
+      timestamp: new Date().toISOString(),
+      'mime-type': 'application/json',
+      payload: {
+        status: 'unscanned',
+        submissionId: message.payload.id,
+        url: message.payload.url,
+        fileName: extractFileNameFromUrl(message.payload.url)
+      }
+    }
+  }
+  if (scoreSystem.topic === 'or.action.review') {
+    const payload = message.payload
+    payload.eventType = 'CREATE'
+    delete payload.originalTopic
+    return {
+      topic: scoreSystem.topic,
+      originator: 'tc-scorecard-processor',
+      timestamp: new Date().toISOString(),
+      'mime-type': 'application/json',
+      payload
+    }
+  }
+  // add handling for other topics in future
+
+  throw new Error(`Unsupported score system topic: ${scoreSystem.topic}`)
+}
+
+/**
+ * Send message to Kafka.
+ * @param {Object} message the kafka message to send.
+ */
+async function sendMessage (message) {
+  if (process.env.NODE_ENV === 'test') {
+    logger.debug(`Send Kafka message to topic: ${message.topic}`)
+    logger.debug(`Payload: ${JSON.stringify(message)}`)
+  } else {
+    // init producer if needed
+    if (!producer) {
+      producer = new Kafka.Producer(helper.getKafkaOptions())
+      // init kafka producer
+      try {
+        await producer.init()
+      } catch (e) {
+        // if there is any error, reset producer to null so that it will be re-created next time
+        producer = null
+        throw e
+      }
+    }
+    // send message
+    await producer.send({
+      topic: message.topic,
+      message: {
+        value: JSON.stringify(message)
+      }
+    })
+  }
+}
+
+/**
+ * Process create/update submission message
+ * @param {Object} message the kafka message
+ */
+async function processSubmission (message) {
+  // get M2M token
+  logger.debug('Get M2M token')
+  const m2mToken = await helper.getM2Mtoken()
+
+  // get challenge details
+  logger.debug('Get challenge details')
+  const challengeId = message.payload.legacyChallengeId
+  const challengeRes = await helper.getRequest(`${config.CHALLENGE_API_URL}/${challengeId}`,
+    {}, m2mToken)
+  if (!_.get(challengeRes, 'body.result.success')) {
+    throw new Error(`Failed to get challenge of id ${challengeId}`)
+  }
+  const challenge = _.get(challengeRes, 'body.result.content')
+  // get scorecard id and phase from challenge details
+  const scorecardId = challenge.reviewScorecardId
+  if (!scorecardId) {
+    throw new Error(`Missing review scorecard id for challenge id ${challengeId}`)
+  }
+  const currentPhase = challenge.currentPhaseName
+  if (!currentPhase || currentPhase.length === 0) {
+    throw new Error(`Missing current phase for challenge id ${challengeId}`)
+  }
+  logger.debug(`Scorecard id: ${scorecardId}`)
+  logger.debug(`Current phase: ${currentPhase}`)
+
+  // get scorecard details
+  logger.debug('Get scorecard details')
+  const scorecardRes = await helper.getRequest(config.SCORECARD_API_URL, { legacyId: scorecardId }, m2mToken)
+  const scorecardDetails = _.get(scorecardRes, 'body[0].scorecardDetails', [])
+  if (scorecardDetails.length === 0) {
+    throw new Error(`There are no scorecard details for scorecard id: ${scorecardId}`)
+  }
+
+  // create message for each active score system matching current phase
+  for (let i = 0; i < scorecardDetails.length; i += 1) {
+    const scoreSystem = scorecardDetails[i]
+    if (scoreSystem.isActive && scoreSystem.phase.toLowerCase() === currentPhase.toLowerCase()) {
+      const newMsg = generateScoreSystemMessage(message, scoreSystem)
+      logger.debug(`Post Kafka message for score system ${scoreSystem.name}: ${JSON.stringify(newMsg, null, 4)}`)
+      // send message
+      await sendMessage(newMsg)
+    }
+  }
+}
+
+processSubmission.schema = {
+  message: joi.object().keys({
+    topic: joi.string().required(),
+    originator: joi.string().required(),
+    timestamp: joi.date().required(),
+    'mime-type': joi.string().required(),
+    payload: joi.object().keys({
+      originalTopic: joi.string().valid(config.CREATE_SUBMISSION_TOPIC).required(),
+      resource: joi.string().valid('submission').required(),
+      id: joi.string().guid().required(),
+      type: joi.string().valid('Contest Submission').required(),
+      url: joi.string().uri().required(),
+      legacyChallengeId: joi.number().integer().min(1).required()
+    }).unknown(true).required()
+  }).required()
+}
+
+module.exports = {
+  processSubmission
+}
+
+logger.buildService(module.exports)
diff --git a/test/common/prepare.js b/test/common/prepare.js
new file mode 100644
index 0000000..5a60e35
--- /dev/null
+++ b/test/common/prepare.js
@@ -0,0 +1,46 @@
+/*
+ * Setting up Mock for all tests
+ */
+
+const nock = require('nock')
+const prepare = require('mocha-prepare')
+const testData = require('../common/testData')
+
+prepare(function (done) {
+  nock(/\.com/)
+    .persist()
+    .post('/oauth/token')
+    .reply(200, { access_token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIiwiQ29ubmVjdCBTdXBwb3J0IiwiYWRtaW5pc3RyYXRvciIsInRlc3RSb2xlIiwiYWFhIiwidG9ueV90ZXN0XzEiLCJDb25uZWN0IE1hbmFnZXIiLCJDb25uZWN0IEFkbWluIiwiY29waWxvdCIsIkNvbm5lY3QgQ29waWxvdCBNYW5hZ2VyIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJUb255SiIsImV4cCI6MTU2NTY4MTkyMCwidXNlcklkIjoiODU0Nzg5OSIsImlhdCI6MTU1NTY4MTMyMCwiZW1haWwiOiJhamVmdHNAdG9wY29kZXIuY29tIiwianRpIjoiMTlhMDkzNzAtMjk4OC00N2I4LTkxODktMGRhODVjNjM0ZWQyIn0.V8nsQpbzQ_4iEd0dAbuYsfeydnhSAEQ95AKKwl8RONw' })
+    .get('/v4/challenges/30049360')
+    .reply(200, testData.challenges['30049360'])
+    .get('/v4/challenges/30054674')
+    .reply(200, testData.challenges['30054674'])
+    .get('/v4/challenges/89898989')
+    .reply(404, testData.challenges['89898989'])
+    .get('/v5/submissions?legacySubmissionId=206743&')
+    .reply(200, [{ id: 'b91a0ca3-3988-4899-bab4-c789f22def39' }])
+    .get('/v5/submissions?legacySubmissionId=111111111&')
+    .reply(200, [])
+    .get('/v5/reviewTypes?isActive=true&name=Review&perPage=100&')
+    .reply(200, [testData.reviewTypes[0]], { 'X-Total-Pages': 2 })
+    .get('/v5/reviewTypes?isActive=true&name=Review&page=2&perPage=100&')
+    .reply(200, [testData.reviewTypes[1]], { 'X-Total-Pages': 2 })
+    .get('/v5/reviewTypes?isActive=true&name=Post-Mortem&perPage=100&')
+    .reply(200, [], { 'X-Total-Pages': 1 })
+    .get('/v5/reviews?reviewerId=151743&scoreCardId=300001610&submissionId=b91a0ca3-3988-4899-bab4-c789f22def39&')
+    .reply(200, testData.reviews, { 'X-Total-Pages': 1 })
+    .get('/v5/reviews?reviewerId=151743&scoreCardId=300001611&submissionId=b91a0ca3-3988-4899-bab4-c789f22def39&')
+    .reply(200, [], { 'X-Total-Pages': 1 })
+    .put('/v5/reviews/9c1c080a-b54f-46c4-b87b-6218038be765')
+    .reply(200)
+    .post('/v5/reviews')
+    .reply(200)
+    .get(/v5\/scorecards\?legacyId=.+/)
+    .reply(200, [{ 'id': 'b9956051-4749-4912-abd5-bf4d701af891', 'scorecardDetails': [{ 'id': 'b9956051-4749-4912-abd1-af4d701af891', 'name': 'AV Scan', 'phase': 'submission', 'isActive': true, 'topic': 'avscan.action.scan', 'weight': 25 }, { 'id': 'b9956051-4749-4912-abd1-af4d701af892', 'name': 'OR', 'phase': 'review', 'isActive': true, 'topic': 'or.action.review', 'weight': 25 }, { 'id': 'b9956051-4749-4912-abd1-af4d701af893', 'name': 'AV Scan', 'phase': 'registration', 'isActive': true, 'topic': 'avscan.action.scan', 'weight': 25 }, { 'id': 'b9956051-4749-4912-abd1-af4d701af894', 'name': 'OR', 'phase': 'registration', 'isActive': true, 'topic': 'or.action.review', 'weight': 25 }] }])
+
+  done()
+}, function (done) {
+// called after all test completes (regardless of errors)
+  nock.cleanAll()
+  done()
+})
diff --git a/test/common/testData.js b/test/common/testData.js
index d134d89..1025676 100644
--- a/test/common/testData.js
+++ b/test/common/testData.js
@@ -2,6 +2,10 @@
  * Test data to be used in tests
  */
 
+const avScanTopic = 'avscan.action.scan'
+
+const reviewActionTopic = 'or.action.review'
+
 const testTopics = {
   'create': {
     requiredFields: ['topic', 'originator', 'timestamp', 'mime-type',
@@ -11,7 +15,7 @@ const testTopics = {
       'payload.reviewerId', 'payload.reviewTypeId'],
     stringFields: ['payload.eventType'],
     testMessage: {
-      topic: 'or.notification.create',
+      topic: 'submission.notification.score',
       originator: 'or-app',
       timestamp: '2019-02-25T00:00:00',
       'mime-type': 'application/json',
@@ -34,7 +38,7 @@ const testTopics = {
       'payload.reviewerId', 'payload.reviewTypeId'],
     stringFields: ['payload.userId', 'payload.eventType'],
     testMessage: {
-      topic: 'or.notification.create',
+      topic: 'submission.notification.score',
       originator: 'or-app',
       timestamp: '2019-02-25T00:00:00',
       'mime-type': 'application/json',
@@ -49,9 +53,707 @@ const testTopics = {
         eventType: 'UPDATE'
       }
     }
+  },
+  'submission.notification.aggregate': {
+    operation: 'create',
+    requiredFields: ['topic', 'originator', 'timestamp', 'mime-type',
+      'payload.resource', 'payload.id', 'payload.url',
+      'payload.legacyChallengeId'],
+    integerFields: ['payload.legacyChallengeId'],
+    stringFields: ['originator', 'mime-type', 'payload.resource', 'payload.id',
+      'payload.url'],
+    dateFields: ['timestamp'],
+    booleanFields: [],
+    testMessage: {
+      topic: 'submission.notification.aggregate',
+      originator: 'or-app',
+      timestamp: '2019-02-25T00:00:00',
+      'mime-type': 'application/json',
+      payload: {
+        originalTopic: 'submission.notification.create',
+        resource: 'submission',
+        id: '104366f8-f46b-45db-a971-11bc69e6c8ff',
+        type: 'Contest Submission',
+        url: 'https://s3.amazonaws.com/topcoder-dev-submissions-dmz/30054740-8547899-SUBMISSION_ZIP-1554188341581.zip?query=test',
+        memberId: 12345,
+        legacyChallengeId: 30049360,
+        created: '2019-04-02T06:59:29.785Z',
+        updated: '2019-04-03T06:59:29.785Z',
+        createdBy: 'user1',
+        updatedBy: 'user2',
+        submissionPhaseId: 123123,
+        fileType: 'zip',
+        isFileSubmission: false
+      }
+    }
+  }
+}
+
+const challenges = {
+  30049360: {
+    'id': '4da4e65e:16cb911536f:4771',
+    'result': {
+      'success': true,
+      'status': 200,
+      'metadata': null,
+      'content': {
+        'subTrack': 'CODE',
+        'challengeTitle': 'Code Dev-Env Test',
+        'challengeId': 30049360,
+        'projectId': 7572,
+        'forumId': 28457,
+        'detailedRequirements': '<p>testing</p>\n',
+        'reviewScorecardId': 30001610,
+        'numberOfCheckpointsPrizes': 0,
+        'postingDate': '2015-07-27T13:00:00.000Z',
+        'registrationEndDate': '2019-12-02T14:00:00.000Z',
+        'submissionEndDate': '2019-12-02T14:00:00.000Z',
+        'reviewType': 'COMMUNITY',
+        'forumLink': 'https://apps.topcoder.com/forums/?module=Category&categoryID=28457',
+        'appealsEndDate': '2019-12-06T02:00:00.000Z',
+        'currentStatus': 'Active',
+        'challengeCommunity': 'develop',
+        'directUrl': 'https://www.topcoder.com/direct/contest/detail.action?projectId=30049360',
+        'prizes': [
+          350.0,
+          150.0
+        ],
+        'terms': [
+          {
+            'termsOfUseId': 20704,
+            'role': 'Primary Screener',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 21193,
+            'role': 'Submitter',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Terms for TopCoder Competitions v2.1',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Aggregator',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Specification Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Final Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20794,
+            'role': 'Manager',
+            'agreeabilityType': 'Non-electronically-agreeable',
+            'title': 'Approved OR Managers - TopCoder Technical Team',
+            'url': 'http://www.topcoder.com'
+          },
+          {
+            'termsOfUseId': 20893,
+            'role': 'Copilot',
+            'agreeabilityType': 'Non-electronically-agreeable',
+            'title': 'TopCoder Master Services Agreement',
+            'url': 'http://www.topcoder.com/wiki/download/attachments/35129137/Member+Master+Agreement+v0020409.pdf'
+          }
+        ],
+        'finalSubmissionGuidelines': '<p>testing</p>\n',
+        'technologies': [
+          '.NET'
+        ],
+        'platforms': [
+          'Android'
+        ],
+        'currentPhaseName': 'Registration',
+        'currentPhaseRemainingTime': 5962969,
+        'currentPhaseEndDate': '2019-12-02T14:00:00.000Z',
+        'registrants': [
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-27T17:20:32.000Z',
+            'submissionDate': '2018-08-24T19:51:34.000Z',
+            'handle': 'TonyJ'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-29T00:38:21.000Z',
+            'handle': 'Ghostar'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-29T00:42:04.000Z',
+            'submissionDate': '2015-10-29T04:21:18.000Z',
+            'handle': 'hohosky'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-29T01:46:16.000Z',
+            'handle': 'DhananjayKumar1'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-29T04:55:29.000Z',
+            'submissionDate': '2015-10-29T05:06:51.000Z',
+            'handle': 'dplass'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-10-29T05:09:02.000Z',
+            'submissionDate': '2015-10-29T06:20:36.000Z',
+            'handle': 'dmwright'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2015-07-30T23:37:34.000Z',
+            'submissionDate': '2015-10-29T00:01:36.000Z',
+            'handle': 'albertwang'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2017-10-07T14:03:34.000Z',
+            'submissionDate': '2017-11-28T20:28:56.000Z',
+            'handle': 'dan_developer'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2017-10-13T17:57:34.000Z',
+            'handle': 'tjefts_block15'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2017-10-13T17:58:56.000Z',
+            'handle': 'tjefts_block20'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2017-11-11T20:53:27.000Z',
+            'submissionDate': '2018-03-15T06:39:40.033Z',
+            'handle': 'amy_admin'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2018-03-11T09:02:55.000Z',
+            'handle': 'kevinkid'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2018-03-23T08:17:30.000Z',
+            'handle': 'sushil1000'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2018-05-24T21:19:45.000Z',
+            'handle': 'bop_t26'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2018-08-20T23:39:04.000Z',
+            'handle': 'hoho123456'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2018-10-22T14:48:10.000Z',
+            'handle': 'TestAccount1'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-04-08T15:14:39.000Z',
+            'handle': 'huanner'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-05-13T19:02:21.238Z',
+            'handle': 'lazybaer'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-08-01T17:29:50.000Z',
+            'handle': 'callmekatootie'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #555555',
+            'rating': 1,
+            'registrationDate': '2019-08-03T06:36:25.000Z',
+            'handle': 'easteregg'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-08-03T09:31:02.000Z',
+            'handle': 'FireIce'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-08-26T12:22:53.000Z',
+            'handle': 'jcori'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-09-20T10:41:52.000Z',
+            'handle': 'mess'
+          }
+        ],
+        'phases': [
+          {
+            'duration': 137293200000,
+            'actualStartTime': '2015-07-27T13:00:00.000Z',
+            'scheduledStartTime': '2015-07-27T13:00:00.000Z',
+            'phaseId': 733195,
+            'scheduledEndTime': '2019-12-02T14:00:00.000Z',
+            'fixedStartTime': '2015-07-27T13:00:00.000Z',
+            'type': 'Registration',
+            'status': 'Open'
+          },
+          {
+            'duration': 137292900000,
+            'scheduledStartTime': '2015-07-27T13:05:00.000Z',
+            'phaseId': 733196,
+            'scheduledEndTime': '2019-12-02T14:00:00.000Z',
+            'type': 'Submission',
+            'status': 'Closed'
+          },
+          {
+            'duration': 172800000,
+            'scheduledStartTime': '2019-12-02T14:00:00.000Z',
+            'phaseId': 733197,
+            'scheduledEndTime': '2019-12-04T14:00:00.000Z',
+            'type': 'Review',
+            'status': 'Scheduled'
+          },
+          {
+            'duration': 86400000,
+            'scheduledStartTime': '2019-12-04T14:00:00.000Z',
+            'phaseId': 733198,
+            'scheduledEndTime': '2019-12-05T14:00:00.000Z',
+            'type': 'Appeals',
+            'status': 'Scheduled'
+          },
+          {
+            'duration': 43200000,
+            'scheduledStartTime': '2019-12-05T14:00:00.000Z',
+            'phaseId': 733199,
+            'scheduledEndTime': '2019-12-06T02:00:00.000Z',
+            'type': 'Appeals Response',
+            'status': 'Scheduled'
+          }
+        ],
+        'submissions': [
+          {
+            'submitter': 'albertwang',
+            'submitterId': 10336829,
+            'submissions': [
+              {
+                'submissionId': 509262,
+                'submissionStatus': 'Active',
+                'submissionTime': '2015-10-29T00:01:36.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'hohosky',
+            'submitterId': 16096823,
+            'submissions': [
+              {
+                'submissionId': 509263,
+                'submissionStatus': 'Active',
+                'submissionTime': '2015-10-29T04:21:18.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'dplass',
+            'submitterId': 251184,
+            'submissions': [
+              {
+                'submissionId': 509265,
+                'submissionStatus': 'Active',
+                'submissionTime': '2015-10-29T05:06:51.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'dmwright',
+            'submitterId': 114853,
+            'submissions': [
+              {
+                'submissionId': 509267,
+                'submissionStatus': 'Active',
+                'submissionTime': '2015-10-29T06:20:36.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'TonyJ',
+            'submitterId': 8547899,
+            'submissions': [
+              {
+                'submissionId': 205459,
+                'submissionStatus': 'Active',
+                'submissionTime': '2018-08-24T19:51:34.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'amy_admin',
+            'submitterId': 40153455,
+            'submissions': [
+              {
+                'submissionId': 204922,
+                'submissionStatus': 'Active',
+                'submissionTime': '2018-03-15T06:39:40.033Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'dan_developer',
+            'submitterId': 40152905,
+            'submissions': [
+              {
+                'submissionId': 509401,
+                'submissionStatus': 'Active',
+                'submissionTime': '2017-11-28T20:28:56.000Z'
+              }
+            ]
+          }
+        ],
+        'checkpoints': [],
+        'numberOfRegistrants': 23,
+        'numberOfSubmissions': 7,
+        'numberOfSubmitters': 7
+      }
+    },
+    'version': 'v3'
+  },
+  30054674: {
+    'id': '4da4e65e:16cb911536f:4774',
+    'result': {
+      'success': true,
+      'status': 200,
+      'metadata': null,
+      'content': {
+        'subTrack': 'CODE',
+        'challengeTitle': 'Test for  submission review app api 12345',
+        'challengeId': 30054674,
+        'projectId': 7817,
+        'forumId': 32818,
+        'detailedRequirements': '<p><em>[This contest specification will be made available to all competitors for an Assembly competition. It is intended to give the competitors (and reviewers) all the necessary information and detailed instructions to understand what is expected for the Assembly competition.</em></p>\n\n<p><span style="color:rgb(0, 112, 192)"><strong><em>This specification should not include any company specific information or proprietary information because it will be available to users who have not signed confidentiality assignments.</em></strong></span></p>\n\n<p><span style="color:rgb(0, 112, 192)"><em>This specification will be reviewed internally by TopCoder to verify the following points:</em></span></p>\n\n<ul>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the spec clear? Is it attractive to competitors? Is there anything that could be done to clarify or improve the specification? &nbsp;&nbsp;</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Are the requirements for the competition clear in detail and scope?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Are the deliverables for the competition clear in detail and scope? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the design clear - are there any details that are missing that competitors will need to complete in this project?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the timeline appropriate?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the prize structure appropriate?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Overall the specification is appropriate for production?</em></span></li>\n</ul>\n\n<p><span style="color:rgb(0, 112, 192)"><em>The Architect will be responsible for this specification. However, there are numerous sections that will be completed by the Copilot or the Project Manager.]</em></span></p>\n\n<h2><span style="color:rgb(255, 0, 0)">Project Overview</span></h2>\n\n<p><strong><span style="color:rgb(164, 31, 172)">[Provide an overview of the overall application the Assembly competition is implementing.]</span></strong></p>\n\n<p><span style="font-size:12px">EXAMPLE:</span></p>\n\n<p><span style="font-size:12px">The Sales IM tool is an application that will create a web based instant messaging system. &nbsp;The system &nbsp; &nbsp;will be used installed and run on a company&#39;s web site. The tool will allow potential clients of the company to ask questions and chat with the company.</span></p>\n\n<h2><span style="color:rgb(255, 0, 0)">Competition Task Overview</span></h2>\n\n<p><strong>[Provide an overview of the pieces of the application that the Assembly competition is implementing.]</strong></p>\n\n<p><span style="font-size:12px">EXAMPLE:<br />\nHTML prototype has been converted to JSP pages with the correct flows. The majority of the application logic has been developed inside the components. The main tasks will involve:</span></p>\n\n<ul>\n\t<li><span style="font-size:12px">Configuration of components</span></li>\n\t<li><span style="font-size:12px">Writing any necessary AJAX and JSP code</span></li>\n\t<li><span style="font-size:12px">Writing servlet and action classes and hooking in the necessary components</span></li>\n\t<li><span style="font-size:12px">Writing unit tests</span></li>\n\t<li><span style="font-size:12px">Providing directions for configuration and deployment</span></li>\n</ul>\n\n<p><span style="font-size:12px"><strong><span style="color:rgb(164, 31, 172)">[You should break out 2.X points if there are any complicated instructions to the members.]</span></strong></span></p>\n\n<h3><span style="color:rgb(255, 0, 0)">Testing</span></h3>\n\n<p><strong><span style="color:rgb(164, 31, 172)">[Provide Testing Requirements. This section should include any testing requirements (unit tests) that will help review the application.]</span></strong></p>\n\n<p><span style="font-size:12px">EXAMPLE:<br />\nUnit test are only needed for NASWorker.cs class.</span></p>\n\n<p><span style="font-size:12px">You need to provide manual demos to verify your implementation.</span></p>\n\n<h2><span style="color:rgb(255, 0, 0)">Technology Overview</span></h2>\n\n<p><strong><span style="color:rgb(164, 31, 172)">[List the relevant technologies for the project. This is intended to help the interested competitor determine if they are able to compete on the project. Include any details on VM/etc. in this section.]</span></strong></p>\n\n<p><span style="font-size:12px">EXAMPLE:<br />\nThe working environment requirement details for this application are outlined in the Application Requirements Specification. An overview of the environment requirements are listed below:</span></p>\n\n<ul>\n\t<li><span style="font-size:12px">Java 1.5</span></li>\n\t<li><span style="font-size:12px">Red Hat Linux</span></li>\n\t<li><span style="font-size:12px">JBoss 4.0.2</span></li>\n\t<li><span style="font-size:12px">Tomcat 5.5</span></li>\n\t<li><span style="font-size:12px">Struts 1.3.5</span></li>\n\t<li><span style="font-size:12px">Informix 10.0</span></li>\n\t<li><span style="font-size:12px">AJAX</span></li>\n</ul>\n\n<h2><span style="color:rgb(255, 0, 0)">Documentation Provided</span></h2>\n\n<p><strong><span style="color:rgb(164, 31, 172)">[The majority of the documentation deliverables should be consistent across all applications. However, document any additional information that will be provided for this project and remove any documents in this list that are not applicable.]</span></strong></p>\n\n<p>Documentation and Applications that will be provided to registered members:</p>\n<strong>Document Name</strong><strong>Document Description &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</strong><br />\n<span style="color:rgb(164, 31, 145)">[Deliverable Information]</span><span style="color:rgb(164, 31, 145)">[Deliverable Information]?</span><br />\nRequirements Documentation<br />\n<br />\nDatabase Schema<br />\n<br />\nHTML Prototype<br />\n<br />\nJSP Converted Prototype<br />\n<br />\nSample Data\n<h2><strong><span style="color:rgb(255, 0, 0)">Project Dependencies</span></strong></h2>\n\n<p><span style="font-size:12px">Custom / New Generic Components</span></p>\n\n<p><span style="font-size:12px"><strong><span style="color:rgb(164, 31, 172)">[List all custom and new generic components that are required for this application. &nbsp;This is useful for competitors to know where to look for component information if the component is not in the catalog yet. This is also useful for managers and architects to easily check which new components are dependent on this Assembly.</span></strong></span></p>\n\n<p><span style="font-size:12px"><strong><span style="color:rgb(164, 31, 172)">** Note that all new and custom components will need to be posted to the forums for this competition unless they are made available in the catalog prior to the start of the competition.]</span></strong></span></p>\n\n<div>&nbsp;</div>\n\n<div><strong>Component Name</strong><strong>Version</strong><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Generic / Custom</strong><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Component URL</strong><br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n&nbsp;</div>\n',
+        'reviewScorecardId': 30001610,
+        'numberOfCheckpointsPrizes': 0,
+        'postingDate': '2019-02-05T14:15:18.544Z',
+        'registrationEndDate': '2019-02-06T14:16:59.418Z',
+        'submissionEndDate': '2019-02-06T14:17:07.247Z',
+        'reviewType': 'COMMUNITY',
+        'forumLink': 'https://apps.topcoder.com/forums/?module=Category&categoryID=32818',
+        'appealsEndDate': '2019-02-06T15:09:43.244Z',
+        'currentStatus': 'Completed',
+        'challengeCommunity': 'develop',
+        'directUrl': 'https://www.topcoder.com/direct/contest/detail.action?projectId=30054674',
+        'prizes': [
+          1000.0,
+          500.0
+        ],
+        'terms': [
+          {
+            'termsOfUseId': 20704,
+            'role': 'Primary Screener',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 21303,
+            'role': 'Submitter',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Terms for TopCoder Competitions v2.2',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Aggregator',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Specification Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20704,
+            'role': 'Final Reviewer',
+            'agreeabilityType': 'Electronically-agreeable',
+            'title': 'Standard Reviewer Terms v1.0',
+            'url': ''
+          },
+          {
+            'termsOfUseId': 20794,
+            'role': 'Manager',
+            'agreeabilityType': 'Non-electronically-agreeable',
+            'title': 'Approved OR Managers - TopCoder Technical Team',
+            'url': 'http://www.topcoder.com'
+          },
+          {
+            'termsOfUseId': 20893,
+            'role': 'Copilot',
+            'agreeabilityType': 'Non-electronically-agreeable',
+            'title': 'TopCoder Master Services Agreement',
+            'url': 'http://www.topcoder.com/wiki/download/attachments/35129137/Member+Master+Agreement+v0020409.pdf'
+          }
+        ],
+        'winners': [
+          {
+            'submitter': 'denis',
+            'submissionId': 206743,
+            'rank': 1,
+            'submissionTime': '2019-02-05T15:58:32.000Z',
+            'points': 96.25
+          },
+          {
+            'submitter': 'lars2520',
+            'submissionId': 206744,
+            'rank': 2,
+            'submissionTime': '2019-02-05T16:00:20.000Z',
+            'points': 92.5
+          }
+        ],
+        'finalSubmissionGuidelines': '<p><em>[This contest specification will be made available to all competitors for an Assembly competition. It is intended to give the competitors (and reviewers) all the necessary information and detailed instructions to understand what is expected for the Assembly competition.</em></p>\n\n<p><span style="color:rgb(0, 112, 192)"><strong><em>This specification should not include any company specific information or proprietary information because it will be available to users who have not signed confidentiality assignments.</em></strong></span></p>\n\n<p><span style="color:rgb(0, 112, 192)"><em>This specification will be reviewed internally by TopCoder to verify the following points:</em></span></p>\n\n<ul>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the spec clear? Is it attractive to competitors? Is there anything that could be done to clarify or improve the specification? &nbsp;&nbsp;</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Are the requirements for the competition clear in detail and scope?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Are the deliverables for the competition clear in detail and scope? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the design clear - are there any details that are missing that competitors will need to complete in this project?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the timeline appropriate?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Is the prize structure appropriate?</em></span></li>\n\t<li><span style="color:rgb(0, 112, 192)"><em>Overall the specification is appropriate for production?</em></span></li>\n</ul>\n\n<p><span style="color:rgb(0, 112, 192)"><em>The Architect will be responsible for this specification. However, there are numerous sections that will be completed by the Copilot or the Project Manager.]</em></span></p>\n\n<h2><strong><span style="color:#FF0000">Submission Deliverables</span></strong></h2>\n\n<p><span style="font-size:12px">A complete list of deliverables can be viewed in the TopCoder Assembly competition Tutorial at: <a href="http://apps.topcoder.com/wiki/display/tc/Assembly+Competition+Tutorials">http://apps.topcoder.com/wiki/display/tc/Assembly+Competition+Tutorials&nbsp;</a></span></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[Document any specific deliverables associated with this competition]</strong></span></span></p>\n\n<p><span style="font-size:12px">EXAMPLE:<br />\nBelow is an overview of the deliverables:</span></p>\n\n<ul>\n\t<li><span style="font-size:12px">Fully Implemented IM Tool functionality defined by the requirements documentation for the sections defined in the milestone sections.</span></li>\n\t<li><span style="font-size:12px">A complete and detailed deployment documented explaining how to deploy the application including configuration information.</span></li>\n\t<li><span style="font-size:12px">JUNIT Tests to verify your application successfully meets the requirements of the application.</span></li>\n\t<li><span style="font-size:12px">The Ant build script to create the war files. This can be highly variable per competition so be sure to specify necessary deliverables clearly.</span></li>\n</ul>\n\n<h2><span style="color:#FF0000"><strong>Final Submission</strong></span></h2>\n\n<p><span style="font-size:12px">For each member, the final submission should be uploaded via the challenge detail page on <a href="http://www.topcoder.com">topcoder.com</a>.</span></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[Add any special instructions or restrictions on submission here.]</strong></span></span></p>\n\n<h2><span style="color:#FF0000"><strong>Environment Setup</strong></span></h2>\n\n<p><span style="font-size:12px"><strong><span style="color:#a41f91">[By preparing a ready-to-use development environment, you can greatly increase the chances for a high quality submission. Try to give competitors an environment that needs minimal configuration and setup so members can focus on coding a solution rather than preparing to code one. Absolutely critical to this setup is providing valid test data. Relying on competitors to make their test data is error prone and will lead to other issues in downstream development efforts.]</span></strong></span></p>\n\n<p><strong><span style="color:#0000FF">Source code setup</span></strong></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[The architect should document how the source code should be set up and packaged if different from the standard used in Assemblies.]</strong></span></span></p>\n\n<p><span style="color:#0000FF"><strong>Build Setup</strong></span></p>\n\n<p><span style="font-size:12px"><strong><span style="color:#a41f91">[Document all the ant tasks that are required.]</span></strong></span></p>\n\n<p><span style="font-size:12px">The ant &#39;compile&#39; and ant &#39;build&#39; commands should be implemented to compile the source code and create the war file.</span></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[Add something about how you can run an ant task to clear test data]</strong></span></span></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[Add something about how you can run an ant task to load the lookup / sample data]</strong></span></span></p>\n\n<p><strong><span style="color:#0000FF">SVN Access</span></strong></p>\n\n<p><span style="font-size:12px"><span style="color:#a41f91"><strong>[Each member might need to be assigned SVN access. Please list all SVN branches which members need to request access to.]</strong></span></span></p>\n\n<div><strong>Repository Name</strong><strong>URL</strong><br />\nOnline Review<a href="https://coder.topcoder.com/tcs/clients/name/branches">https://coder.topcoder.com/tcs/clients/name/branches</a><br />\nStudio<a href="https://coder.topcoder.com/client/branches/name">https://coder.topcoder.com/client/branches/name</a><br />\nDatabases<a href="https://coder.topcoder.com/client/trunk">https://coder.topcoder.com/client/trunk</a></div>\n\n<h2><span style="color:#FF0000"><strong>Development Environment</strong></span></h2>\n\n<p><span style="font-size:12px"><strong><span style="color:#a41f91">[This section should document what environment software will be available to each member.</span></strong></span></p>\n\n<p><span style="font-size:12px"><strong><span style="color:#a41f91">For example:</span></strong></span></p>\n\n<ul>\n\t<li><span style="font-size:12px"><strong><span style="color:#a41f91">SVN access</span></strong></span></li>\n\t<li><span style="font-size:12px"><strong><span style="color:#a41f91">Amazon VM(s)</span></strong></span></li>\n\t<li><span style="font-size:12px"><strong><span style="color:#a41f91">VPN access</span></strong></span></li>\n</ul>\n\n<p><span style="font-size:12px"><strong><span style="color:#a41f91">Document how members will be given access / permissions]</span></strong></span></p>\n',
+        'technologies': [
+          'Android'
+        ],
+        'platforms': [
+          'Android'
+        ],
+        'currentPhaseName': 'Stalled',
+        'registrants': [
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-02-05T15:47:19.080Z',
+            'submissionDate': '2019-02-05T15:58:32.000Z',
+            'handle': 'denis'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-02-05T15:53:34.534Z',
+            'submissionDate': '2019-02-05T16:00:20.000Z',
+            'handle': 'lars2520'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-03-19T08:38:04.399Z',
+            'handle': 'easteregg'
+          },
+          {
+            'reliability': null,
+            'colorStyle': 'color: #151516',
+            'registrationDate': '2019-09-13T14:39:24.097Z',
+            'handle': 'sachin-kumar'
+          }
+        ],
+        'phases': [
+          {
+            'duration': 86400000,
+            'actualStartTime': '2019-02-05T14:15:18.544Z',
+            'scheduledStartTime': '2019-02-05T14:15:18.544Z',
+            'phaseId': 764423,
+            'scheduledEndTime': '2019-02-06T14:16:59.418Z',
+            'fixedStartTime': '2019-02-05T14:00:00.000Z',
+            'actualEndTime': '2019-02-06T14:16:59.418Z',
+            'type': 'Registration',
+            'status': 'Closed'
+          },
+          {
+            'duration': 86100000,
+            'actualStartTime': '2019-02-05T14:20:39.454Z',
+            'scheduledStartTime': '2019-02-05T14:20:39.454Z',
+            'phaseId': 764424,
+            'scheduledEndTime': '2019-02-06T14:17:07.247Z',
+            'actualEndTime': '2019-02-06T14:17:07.247Z',
+            'type': 'Submission',
+            'status': 'Closed'
+          },
+          {
+            'duration': 172800000,
+            'actualStartTime': '2019-02-06T14:17:14.057Z',
+            'scheduledStartTime': '2019-02-06T14:17:14.057Z',
+            'phaseId': 764425,
+            'scheduledEndTime': '2019-02-06T14:42:50.396Z',
+            'actualEndTime': '2019-02-06T14:42:50.396Z',
+            'type': 'Review',
+            'status': 'Closed'
+          },
+          {
+            'duration': 86400000,
+            'actualStartTime': '2019-02-06T14:42:53.338Z',
+            'scheduledStartTime': '2019-02-06T14:42:53.338Z',
+            'phaseId': 764426,
+            'scheduledEndTime': '2019-02-06T14:48:45.275Z',
+            'actualEndTime': '2019-02-06T14:48:45.275Z',
+            'type': 'Appeals',
+            'status': 'Closed'
+          },
+          {
+            'duration': 43200000,
+            'actualStartTime': '2019-02-06T14:48:48.059Z',
+            'scheduledStartTime': '2019-02-06T14:48:48.059Z',
+            'phaseId': 764427,
+            'scheduledEndTime': '2019-02-06T15:09:43.244Z',
+            'actualEndTime': '2019-02-06T15:09:43.244Z',
+            'type': 'Appeals Response',
+            'status': 'Closed'
+          }
+        ],
+        'submissions': [
+          {
+            'submitter': 'denis',
+            'submitterId': 251280,
+            'submissions': [
+              {
+                'finalScore': 96.25,
+                'submissionId': 206743,
+                'submissionStatus': 'Active',
+                'initialScore': 95,
+                'placement': 1,
+                'submissionTime': '2019-02-05T15:58:32.000Z'
+              }
+            ]
+          },
+          {
+            'submitter': 'lars2520',
+            'submitterId': 287131,
+            'submissions': [
+              {
+                'finalScore': 92.5,
+                'submissionId': 206744,
+                'submissionStatus': 'Completed Without Win',
+                'initialScore': 90,
+                'placement': 2,
+                'submissionTime': '2019-02-05T16:00:20.000Z'
+              }
+            ]
+          }
+        ],
+        'checkpoints': [],
+        'numberOfRegistrants': 4,
+        'numberOfSubmissions': 2,
+        'numberOfSubmitters': 2
+      }
+    },
+    'version': 'v3'
+  },
+  89898989: {
+    'id': '4da4e65e:16cb911536f:4772',
+    'result': {
+      'success': true,
+      'status': 404,
+      'metadata': null,
+      'content': 'The challenge does not exists with the id:89898989'
+    },
+    'version': 'v3'
   }
 }
 
+const reviewTypes = [
+  {
+    name: 'Review',
+    id: 'ff5742d6-22bf-4734-b632-add6641078be',
+    isActive: true
+  },
+  {
+    name: 'test-for-review',
+    id: 'af5742d6-22bf-4734-b632-add6641078be',
+    isActive: true
+  }
+]
+
+const reviews = [
+  {
+    'legacyReviewId': 123456788,
+    'score': 92.5,
+    'updatedBy': 'callmekatootie',
+    'reviewerId': 'c56a4180-65aa-42ec-a945-5fd21d3d26f8',
+    'submissionId': 'a12a4180-65aa-42ec-a945-5fd21dec0505',
+    'createdBy': 'callmekatootie',
+    'created': '2019-09-24T00:37:38.537Z',
+    'scoreCardId': 123456789,
+    'typeId': 'c56a4180-65aa-42ec-a945-5fd21dec0503',
+    'id': '9c1c080a-b54f-46c4-b87b-6218038be765',
+    'updated': '2019-09-24T00:37:38.537Z',
+    'status': 'queued'
+  },
+  {
+    'score': 100,
+    'updatedBy': 'maE2maBSv9fRVHjSlC31LFZSq6VhhZqC@clients',
+    'reviewerId': '7b3e99d2-cc1f-43d8-811d-350b48267589',
+    'submissionId': 'b91a0ca3-3988-4899-bab4-c789f22def39',
+    'createdBy': 'maE2maBSv9fRVHjSlC31LFZSq6VhhZqC@clients',
+    'created': '2019-09-23T17:25:04.255Z',
+    'scoreCardId': 30001850,
+    'typeId': '68c5a381-c8ab-48af-92a7-7a869a4ee6c3',
+    'id': '41f30ab2-726f-4f4c-a922-c46eff0d7256',
+    'updated': '2019-09-23T17:25:04.255Z',
+    'status': 'completed'
+  }
+]
+
 module.exports = {
-  testTopics
+  avScanTopic,
+  reviewActionTopic,
+  testTopics,
+  challenges,
+  reviewTypes,
+  reviews
 }
diff --git a/test/common/testHelper.js b/test/common/testHelper.js
index dca4dcf..e8f5141 100644
--- a/test/common/testHelper.js
+++ b/test/common/testHelper.js
@@ -1,8 +1,136 @@
 /**
- * Contains generic helper methods
+ * Contains generic helper methods for tests
  */
-
+const _ = require('lodash')
 const request = require('superagent')
+const should = require('should')
+const config = require('config')
+const Kafka = require('no-kafka')
+const logger = require('../../src/common/logger')
+const helper = require('../../src/common/helper')
+const testData = require('./testData')
+
+let infoLogs = []
+let errorLogs = []
+let debugLogs = []
+const info = logger.info
+const error = logger.error
+const debug = logger.debug
+
+let app
+let producer
+
+/**
+ * Intercept logger.
+ */
+function interceptLogger () {
+  logger.info = (message) => {
+    infoLogs.push(message)
+    info(message)
+  }
+  logger.debug = (message) => {
+    debugLogs.push(message)
+    debug(message)
+  }
+  logger.error = (message) => {
+    if (_.isError(message)) {
+      errorLogs.push(message.message || '')
+    } else {
+      errorLogs.push(String(message))
+    }
+    error(message)
+  }
+}
+
+/**
+ * Restore logger.
+ */
+function restoreLogger () {
+  logger.error = error
+  logger.info = info
+  logger.debug = debug
+}
+
+/**
+ * Clear intercepted logging.
+ */
+function clearInterceptedLogging () {
+  infoLogs = []
+  debugLogs = []
+  errorLogs = []
+}
+
+/**
+ * Get intercepted error logs.
+ * @returns {Array} the error logs
+ */
+function getErrorLogs () {
+  return errorLogs
+}
+
+/**
+ * Get intercepted info logs.
+ * @returns {Array} the info logs
+ */
+function getInfoLogs () {
+  return infoLogs
+}
+
+/**
+ * Get intercepted debug logs.
+ * @returns {Array} the debug logs
+ */
+function getDebugLogs () {
+  return debugLogs
+}
+
+/**
+ * Assert validation error
+ * @param {Error} err the error
+ * @param {String} message the message
+ */
+function assertValidationError (err, message) {
+  err.isJoi.should.be.true()
+  should.equal(err.name, 'ValidationError')
+  err.details.map(x => x.message).should.containEql(message)
+  errorLogs.should.not.be.empty()
+  errorLogs.should.containEql(err.stack)
+}
+
+/**
+ * Assert error message
+ * @param {String} message the message
+ */
+function assertErrorMessage (message) {
+  errorLogs.should.not.be.empty()
+  errorLogs.join('|').should.containEql(message)
+}
+
+/**
+ * Assert info message
+ * @param {String} message the message
+ */
+function assertInfoMessage (message) {
+  infoLogs.should.not.be.empty()
+  infoLogs.join('|').should.containEql(message)
+}
+
+/**
+ * Assert debug message
+ * @param {String} message the message
+ */
+function assertDebugMessage (message) {
+  debugLogs.should.not.be.empty()
+  debugLogs.join('|').should.containEql(message)
+}
+
+/**
+ * Assert no debug message
+ * @param {String} message the message
+ */
+function assertNoDebugMessage (message) {
+  debugLogs.join('|').should.not.containEql(message)
+}
 
 /**
  * Uses superagent to proxy delete request
@@ -18,6 +146,136 @@ async function deleteRequest (url, m2mToken) {
     .set('Accept', 'application/json')
 }
 
+/**
+ * Sleep with time from input
+ * @param {Number} time the time input
+ */
+async function sleep (time) {
+  await new Promise((resolve) => {
+    setTimeout(resolve, time)
+  })
+}
+
+/**
+ * Init producer
+ */
+async function initProducer () {
+  producer = new Kafka.Producer(helper.getKafkaOptions())
+  await producer.init()
+}
+
+/**
+ * Stop producer
+ */
+async function stopProducer () {
+  try {
+    await producer.end()
+  } catch (err) {
+    // ignore
+  }
+}
+
+/**
+ * Get producer
+ * @returns {Object} the producer
+ */
+function getProducer () {
+  return producer
+}
+
+/**
+ * Send message
+ * @param {Object} testMessage the test message to send
+ */
+async function sendMessage (testMessage) {
+  await producer.send({
+    topic: testMessage.topic,
+    message: {
+      value: JSON.stringify(testMessage)
+    }
+  })
+}
+
+/**
+ * Consume not committed messages before e2e test
+ */
+async function consumeMessages () {
+  // consume and commit all not processed messages
+  const consumer = new Kafka.GroupConsumer(helper.getKafkaOptions())
+  await consumer.init([{
+    subscriptions: [config.REVIEW_TOPIC, config.AGGREGATE_SUBMISSION_TOPIC,
+      testData.avScanTopic, testData.reviewActionTopic],
+    handler: (messageSet, topic, partition) => Promise.each(messageSet,
+      (m) => consumer.commitOffset({ topic, partition, offset: m.offset }))
+  }])
+  // make sure process all not committed messages before test
+  await sleep(3 * config.WAIT_TIME)
+  await consumer.end()
+}
+
+/**
+ * Wait job finished with successful log or error log is found
+ */
+async function waitJob () {
+  // the message pattern to get topic/partition/offset
+  const messagePattern = /^Handle Kafka event message; Topic: (.+); Partition: (.+); Offset: (.+); Message: (.+).$/
+  while (true) {
+    if (errorLogs.length > 0) {
+      if (infoLogs.length && messagePattern.exec(infoLogs[0])) {
+        const matchResult = messagePattern.exec(infoLogs[0])
+        // only manually commit for error message during test
+        await app.commitOffset({
+          topic: matchResult[1],
+          partition: parseInt(matchResult[2]),
+          offset: parseInt(matchResult[3])
+        })
+      }
+      break
+    }
+    if (debugLogs.some(x => String(x).includes('Successfully processed message'))) {
+      break
+    }
+    // wait
+    await sleep(config.WAIT_TIME)
+  }
+}
+
+/**
+ * Init the processor app
+ */
+async function initApp () {
+  if (!app) {
+    // start the application (kafka listener)
+    app = require('../../src/app')
+    // wait until consumer init successfully
+    while (true) {
+      if (infoLogs.some(x => String(x).includes('Kick Start'))) {
+        break
+      }
+      await sleep(config.WAIT_TIME)
+    }
+  }
+}
+
 module.exports = {
-  deleteRequest
+  interceptLogger,
+  restoreLogger,
+  clearInterceptedLogging,
+  getErrorLogs,
+  getInfoLogs,
+  getDebugLogs,
+  assertValidationError,
+  assertErrorMessage,
+  assertInfoMessage,
+  assertDebugMessage,
+  assertNoDebugMessage,
+  deleteRequest,
+  sleep,
+  initProducer,
+  stopProducer,
+  getProducer,
+  sendMessage,
+  consumeMessages,
+  waitJob,
+  initApp
 }
diff --git a/test/e2e/review.processor.test.js b/test/e2e/review.processor.test.js
new file mode 100644
index 0000000..0d842ab
--- /dev/null
+++ b/test/e2e/review.processor.test.js
@@ -0,0 +1,145 @@
+/**
+ * E2E test of the Scorecard Review Processor.
+ */
+process.env.NODE_ENV = 'test'
+
+global.Promise = require('bluebird')
+
+const _ = require('lodash')
+
+const testHelper = require('../common/testHelper')
+const { testTopics } = require('../common/testData')
+const dataHandler = require('../../src/app')
+
+describe('Topcoder - Scorecard Review Processor E2E Test', () => {
+  before(async () => {
+    // intercept logger
+    testHelper.interceptLogger()
+  })
+
+  after(async () => {
+    testHelper.restoreLogger()
+  })
+
+  beforeEach(() => {
+    testHelper.clearInterceptedLogging()
+  })
+
+  it('Should handle invalid json message', async () => {
+    const { testMessage } = testTopics.create
+    await dataHandler([{ message: { value: '[ invalid' }, offset: 0 }], testMessage.topic, 0)
+    testHelper.assertErrorMessage('Invalid message JSON.')
+  })
+
+  it('Should handle incorrect topic field message', async () => {
+    const { testMessage } = testTopics.create
+    let message = _.cloneDeep(testMessage)
+    message.topic = 'invalid'
+    await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+    testHelper.assertErrorMessage(
+      'The message topic invalid doesn\'t match the Kafka topic submission.notification.score.')
+  })
+
+  it('processor create review success', async () => {
+    await dataHandler([{ message: { value: JSON.stringify(testTopics.create.testMessage) }, offset: 0 }], testTopics.create.testMessage.topic, 0)
+
+    testHelper.assertDebugMessage('Get submission')
+    testHelper.assertDebugMessage('Submission id: b91a0ca3-3988-4899-bab4-c789f22def39')
+    testHelper.assertDebugMessage('Get review type')
+    testHelper.assertDebugMessage('Review type id: ff5742d6-22bf-4734-b632-add6641078be')
+    testHelper.assertDebugMessage('Create review')
+  })
+
+  it('processor update review success', async () => {
+    await dataHandler([{ message: { value: JSON.stringify(testTopics.update.testMessage) }, offset: 0 }], testTopics.update.testMessage.topic, 0)
+
+    testHelper.assertDebugMessage('Get submission')
+    testHelper.assertDebugMessage('Submission id: b91a0ca3-3988-4899-bab4-c789f22def39')
+    testHelper.assertDebugMessage('Get review type')
+    testHelper.assertDebugMessage('Review type id: ff5742d6-22bf-4734-b632-add6641078be')
+    testHelper.assertDebugMessage('Get review')
+    testHelper.assertDebugMessage('Review id: 9c1c080a-b54f-46c4-b87b-6218038be765')
+    testHelper.assertDebugMessage('Update review')
+  })
+
+  it('test invalid parameters, userId is forbidden for create review message.', async () => {
+    let message = _.cloneDeep(testTopics.create.testMessage)
+    message.payload.userId = '12345'
+    await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+    testHelper.assertErrorMessage('"userId" is not allowed')
+  })
+
+  it('test invalid parameters, fail to retrieve review with given criteria.', async () => {
+    let message = _.cloneDeep(testTopics.update.testMessage)
+    message.payload.scorecardId = 300001611
+    await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+    testHelper.assertErrorMessage('Review doesn\'t exist under criteria')
+  })
+
+  it('test invalid eventType, fail to retrieve review with given criteria.', async () => {
+    let message = _.cloneDeep(testTopics.create.testMessage)
+    message.payload.eventType = 'INVALID_TYPE'
+    await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+    testHelper.assertErrorMessage('Invalid or not supported eventType: INVALID_TYPE')
+  })
+
+  for (const op of ['create']) {
+    let { requiredFields, integerFields, stringFields, testMessage } = testTopics[op]
+
+    it('test invalid parameters, field submissionId incorrect', async () => {
+      let message = _.cloneDeep(testMessage)
+      message.payload.submissionId = 111111111
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+      testHelper.assertErrorMessage('Incorrect submission id 111111111')
+    })
+
+    it('test invalid parameters, fail to get reviewType UUID.', async () => {
+      let message = _.cloneDeep(testMessage)
+      message.payload.reviewTypeId = 12
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+      testHelper.assertErrorMessage('Incorrect review type id 12')
+    })
+
+    for (const requiredField of requiredFields) {
+      if (requiredField !== 'topic') {
+        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
+          let message = _.cloneDeep(testMessage)
+          message = _.omit(message, requiredField)
+          await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+          testHelper.assertErrorMessage(`"${_.last(requiredField.split('.'))}" is required`)
+        })
+      }
+    }
+
+    for (const stringField of stringFields) {
+      if (stringField !== 'topic') {
+        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
+          let message = _.cloneDeep(testMessage)
+          _.set(message, stringField, 123)
+          await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+          testHelper.assertErrorMessage(`"${_.last(stringField.split('.'))}" must be a string`)
+        })
+      }
+    }
+
+    for (const integerField of integerFields) {
+      it(`test invalid parameters, invalid integer type field ${integerField}(wrong number)`, async () => {
+        let message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 'string')
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+        testHelper.assertErrorMessage(`"${_.last(integerField.split('.'))}" must be a number`)
+      })
+
+      it(`test invalid parameters, invalid integer type field ${integerField}(wrong integer)`, async () => {
+        let message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 1.1)
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], message.topic, 0)
+        if (integerField === 'payload.reviewTypeId') {
+          testHelper.assertErrorMessage(`"${_.last(integerField.split('.'))}" must be one of [1, 2, 5, 6, 7, 8, 9, 10, 11, 12]`)
+        } else {
+          testHelper.assertErrorMessage(`"${_.last(integerField.split('.'))}" must be an integer`)
+        }
+      })
+    }
+  }
+})
diff --git a/test/e2e/submission.processor.test.js b/test/e2e/submission.processor.test.js
new file mode 100644
index 0000000..75cd8c2
--- /dev/null
+++ b/test/e2e/submission.processor.test.js
@@ -0,0 +1,234 @@
+/**
+ * E2E test of the Scorecard Submission Processor.
+ */
+process.env.NODE_ENV = 'test'
+
+global.Promise = require('bluebird')
+
+const _ = require('lodash')
+const config = require('config')
+const should = require('should')
+const testHelper = require('../common/testHelper')
+const { testTopics, avScanTopic, reviewActionTopic } = require('../common/testData')
+const dataHandler = require('../../src/app')
+
+describe('Topcoder - Scorecard Submission Processor E2E Test', () => {
+  before(async () => {
+    // intercept logger
+    testHelper.interceptLogger()
+  })
+
+  after(async () => {
+    testHelper.restoreLogger()
+  })
+
+  beforeEach(() => {
+    testHelper.clearInterceptedLogging()
+  })
+
+  for (const topic of [config.AGGREGATE_SUBMISSION_TOPIC]) {
+    const { operation, requiredFields, integerFields, stringFields, dateFields,
+      booleanFields, testMessage } = testTopics[topic]
+
+    it('Should handle invalid json message', async () => {
+      await dataHandler([{ message: { value: '[ invalid' }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage('Invalid message JSON.')
+
+      testHelper.assertErrorMessage('Invalid message JSON.')
+    })
+
+    it('Should handle incorrect topic field message', async () => {
+      const message = _.cloneDeep(testMessage)
+      message.topic = 'invalid'
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage(
+        `The message topic invalid doesn't match the Kafka topic ${topic}.`)
+    })
+
+    it(`processor ${operation} submission success`, async () => {
+      await dataHandler([{ message: { value: JSON.stringify(testMessage) }, offset: 0 }], testMessage.topic, 0)
+
+      // check loggin
+      testHelper.assertDebugMessage('Scorecard id: 30001610')
+      testHelper.assertDebugMessage('Current phase: Registration')
+      testHelper.assertDebugMessage('Post Kafka message for score system AV Scan')
+      testHelper.assertDebugMessage(`"topic": "${avScanTopic}"`)
+      testHelper.assertDebugMessage('"originator": "tc-scorecard-processor"')
+      testHelper.assertDebugMessage('"timestamp": "')
+      testHelper.assertDebugMessage('"mime-type": "application/json"')
+      testHelper.assertDebugMessage('"status": "unscanned"')
+      testHelper.assertDebugMessage(`"submissionId": "${testMessage.payload.id}"`)
+      testHelper.assertDebugMessage(`"url": "${testMessage.payload.url}"`)
+      testHelper.assertDebugMessage('"fileName": "30054740-8547899-SUBMISSION_ZIP-1554188341581.zip"')
+      testHelper.assertDebugMessage('Post Kafka message for score system OR')
+      testHelper.assertDebugMessage(`"topic": "${reviewActionTopic}"`)
+      testHelper.assertDebugMessage(`"resource": "${testMessage.payload.resource}"`)
+      testHelper.assertDebugMessage(`"id": "${testMessage.payload.id}"`)
+      testHelper.assertDebugMessage(`"type": "${testMessage.payload.type}"`)
+      testHelper.assertDebugMessage(`"url": "${testMessage.payload.url}"`)
+      testHelper.assertDebugMessage(`"memberId": ${testMessage.payload.memberId}`)
+      testHelper.assertDebugMessage(`"legacyChallengeId": ${testMessage.payload.legacyChallengeId}`)
+      testHelper.assertDebugMessage(`"created": "${testMessage.payload.created}"`)
+      testHelper.assertDebugMessage(`"updated": "${testMessage.payload.updated}"`)
+      testHelper.assertDebugMessage(`"createdBy": "${testMessage.payload.createdBy}"`)
+      testHelper.assertDebugMessage(`"updatedBy": "${testMessage.payload.updatedBy}"`)
+      testHelper.assertDebugMessage(`"submissionPhaseId": ${testMessage.payload.submissionPhaseId}`)
+      testHelper.assertDebugMessage(`"fileType": "${testMessage.payload.fileType}"`)
+      testHelper.assertDebugMessage(`"isFileSubmission": ${testMessage.payload.isFileSubmission ? 'true' : 'false'}`)
+      testHelper.assertDebugMessage(`"eventType": "${operation.toUpperCase()}"`)
+      testHelper.assertDebugMessage('Successfully processed message')
+
+      const debugLogs = testHelper.getDebugLogs()
+      const avScanIndex = _.findIndex(debugLogs, m => m === `Send Kafka message to topic: ${avScanTopic}`)
+
+      debugLogs[avScanIndex + 1].should.startWith('Payload: ')
+      const avScanMessage = JSON.parse(debugLogs[avScanIndex + 1].substring(9))
+
+      // check generated Kafka messages
+      should.equal(avScanMessage.topic, avScanTopic)
+      should.equal(avScanMessage.originator, 'tc-scorecard-processor')
+      should.exist(avScanMessage.timestamp)
+      should.equal(avScanMessage['mime-type'], 'application/json')
+      should.exist(avScanMessage.payload)
+      should.equal(avScanMessage.payload.status, 'unscanned')
+      should.equal(avScanMessage.payload.submissionId, testMessage.payload.id)
+      should.equal(avScanMessage.payload.url, testMessage.payload.url)
+      should.equal(avScanMessage.payload.fileName, '30054740-8547899-SUBMISSION_ZIP-1554188341581.zip')
+
+      const orReviewIndex = _.findIndex(debugLogs, m => m === `Send Kafka message to topic: ${reviewActionTopic}`)
+
+      debugLogs[orReviewIndex + 1].should.startWith('Payload: ')
+      const orReviewMessage = JSON.parse(debugLogs[orReviewIndex + 1].substring(9))
+      should.equal(orReviewMessage.topic, reviewActionTopic)
+      should.equal(orReviewMessage.originator, 'tc-scorecard-processor')
+      should.exist(orReviewMessage.timestamp)
+      should.equal(orReviewMessage['mime-type'], 'application/json')
+      should.exist(orReviewMessage.payload)
+      should.equal(orReviewMessage.payload.resource, testMessage.payload.resource)
+      should.equal(orReviewMessage.payload.id, testMessage.payload.id)
+      should.equal(orReviewMessage.payload.type, testMessage.payload.type)
+      should.equal(orReviewMessage.payload.url, testMessage.payload.url)
+      should.equal(orReviewMessage.payload.memberId, testMessage.payload.memberId)
+      should.equal(orReviewMessage.payload.legacyChallengeId, testMessage.payload.legacyChallengeId)
+      should.equal(orReviewMessage.payload.created, testMessage.payload.created)
+      should.equal(orReviewMessage.payload.updated, testMessage.payload.updated)
+      should.equal(orReviewMessage.payload.createdBy, testMessage.payload.createdBy)
+      should.equal(orReviewMessage.payload.updatedBy, testMessage.payload.updatedBy)
+      should.equal(orReviewMessage.payload.submissionPhaseId, testMessage.payload.submissionPhaseId)
+      should.equal(orReviewMessage.payload.fileType, testMessage.payload.fileType)
+      should.equal(orReviewMessage.payload.isFileSubmission, testMessage.payload.isFileSubmission)
+      should.equal(orReviewMessage.payload.eventType, operation.toUpperCase())
+    })
+
+    it('test challenge not found.', async () => {
+      const message = _.cloneDeep(testMessage)
+      message.payload.legacyChallengeId = 89898989
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+
+      testHelper.assertErrorMessage('Error: cannot GET /v4/challenges/89898989 (404)')
+    })
+
+    it('test no matched score system.', async () => {
+      const message = _.cloneDeep(testMessage)
+      message.payload.legacyChallengeId = 30054674
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+
+      // check logging
+      testHelper.assertDebugMessage('Scorecard id: 30001610')
+      testHelper.assertDebugMessage('Current phase: Stalled')
+      testHelper.assertNoDebugMessage('Post Kafka message for score system')
+
+      // check generated Kafka messages, there should be no new messages
+      const debugLogs = testHelper.getDebugLogs()
+      const avScanIndex = _.findIndex(debugLogs, m => m === `Send Kafka message to topic: ${avScanTopic}`)
+      should.equal(avScanIndex, -1)
+      const orReviewIndex = _.findIndex(debugLogs, m => m === `Send Kafka message to topic: ${reviewActionTopic}`)
+      should.equal(orReviewIndex, -1)
+    })
+
+    it('test invalid parameters, resource field is invalid', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.resource', 'abc')
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage('"resource" must be one of [submission]')
+    })
+
+    it('test invalid parameters, type field is invalid', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.type', 'abc')
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage('"type" must be one of [Contest Submission]')
+    })
+
+    it('test invalid parameters, id field is invalid GUID', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.id', 'invalid-guid')
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage('"id" must be a valid GUID')
+    })
+
+    it('test invalid parameters, url field is invalid URL', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.url', 'invalid-url')
+      await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+      testHelper.assertErrorMessage('"url" must be a valid uri')
+    })
+
+    for (const requiredField of requiredFields) {
+      if (requiredField !== 'topic') {
+        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
+          let message = _.cloneDeep(testMessage)
+          message = _.omit(message, requiredField)
+          await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+          testHelper.assertErrorMessage(`"${_.last(requiredField.split('.'))}" is required`)
+        })
+      }
+    }
+
+    for (const stringField of stringFields) {
+      if (stringField !== 'topic') {
+        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
+          const message = _.cloneDeep(testMessage)
+          _.set(message, stringField, 123)
+          await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+          testHelper.assertErrorMessage(`"${_.last(stringField.split('.'))}" must be a string`)
+        })
+      }
+    }
+
+    for (const dateField of dateFields) {
+      it(`test invalid parameters, invalid date type field ${dateField}`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, dateField, 'invalid-date')
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+        testHelper.assertErrorMessage(
+          `"${_.last(dateField.split('.'))}" must be a number of milliseconds or valid date string`)
+      })
+    }
+
+    for (const booleanField of booleanFields) {
+      it(`test invalid parameters, invalid boolean type field ${booleanField}`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, booleanField, 'abc')
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+        testHelper.assertErrorMessage(`"${_.last(booleanField.split('.'))}" must be a boolean`)
+      })
+    }
+
+    for (const integerField of integerFields) {
+      it(`test invalid parameters, invalid integer type field ${integerField} (wrong number)`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 'string')
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+        testHelper.assertErrorMessage(`"${_.last(integerField.split('.'))}" must be a number`)
+      })
+
+      it(`test invalid parameters, invalid integer type field ${integerField} (wrong integer)`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 1.1)
+        await dataHandler([{ message: { value: JSON.stringify(message) }, offset: 0 }], testMessage.topic, 0)
+        testHelper.assertErrorMessage(`"${_.last(integerField.split('.'))}" must be an integer`)
+      })
+    }
+  }
+})
diff --git a/test/e2e/test.js b/test/e2e/test.js
deleted file mode 100644
index 4084f14..0000000
--- a/test/e2e/test.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * E2E test of the OR Review Processor.
- */
-process.env.NODE_ENV = 'test'
-
-global.Promise = require('bluebird')
-
-const _ = require('lodash')
-const config = require('config')
-const should = require('should')
-const Kafka = require('no-kafka')
-const request = require('superagent')
-const helper = require('../../src/common/helper')
-const logger = require('../../src/common/logger')
-
-const testHelper = require('../common/testHelper')
-const { testTopics } = require('../common/testData')
-
-describe('Topcoder - OR Review Processor E2E Test', () => {
-  let app
-  let m2mToken
-  let infoLogs = []
-  let errorLogs = []
-  let debugLogs = []
-  const info = logger.info
-  const error = logger.error
-  const debug = logger.debug
-
-  const producer = new Kafka.Producer(helper.getKafkaOptions())
-
-  /**
-   * Sleep with time from input
-   * @param time the time input
-   */
-  async function sleep (time) {
-    await new Promise((resolve) => {
-      setTimeout(resolve, time)
-    })
-  }
-
-  /**
-   * Send message
-   * @param testMessage the test message
-   */
-  const sendMessage = async (testMessage) => {
-    await producer.send({
-      topic: testMessage.topic,
-      message: {
-        value: JSON.stringify(testMessage)
-      }
-    })
-  }
-
-  /**
-   * Consume not committed messages before e2e test
-   */
-  const consumeMessages = async () => {
-    // remove all not processed messages
-    const consumer = new Kafka.GroupConsumer(helper.getKafkaOptions())
-    await consumer.init([{
-      subscriptions: [config.OR_REVIEW_TOPIC],
-      handler: (messageSet, topic, partition) => Promise.each(messageSet,
-        (m) => consumer.commitOffset({ topic, partition, offset: m.offset }))
-    }])
-    // make sure process all not committed messages before test
-    await sleep(2 * config.WAIT_TIME)
-    await consumer.end()
-  }
-
-  // the message patter to get topic/partition/offset
-  const messagePattern = /^Handle Kafka event message; Topic: (.+); Partition: (.+); Offset: (.+); Message: (.+).$/
-  /**
-   * Wait job finished with successful log or error log is found
-   */
-  const waitJob = async () => {
-    while (true) {
-      if (errorLogs.length > 0) {
-        if (infoLogs.length && messagePattern.exec(infoLogs[0])) {
-          const matchResult = messagePattern.exec(infoLogs[0])
-          // only manually commit for error message during test
-          await app.commitOffset({
-            topic: matchResult[1],
-            partition: parseInt(matchResult[2]),
-            offset: parseInt(matchResult[3])
-          })
-        }
-        break
-      }
-      if (debugLogs.some(x => String(x).includes('Successfully processed message'))) {
-        break
-      }
-      // use small time to wait job and will use global timeout so will not wait too long
-      await sleep(config.WAIT_TIME)
-    }
-  }
-
-  const assertErrorMessage = (message) => {
-    errorLogs.should.not.be.empty()
-    errorLogs.some(x => String(x).includes(message)).should.be.true()
-  }
-
-  before(async () => {
-    // generate M2M token
-    m2mToken = await helper.getM2Mtoken()
-    // inject logger with log collector
-    logger.info = (message) => {
-      infoLogs.push(message)
-      info(message)
-    }
-    logger.debug = (message) => {
-      debugLogs.push(message)
-      debug(message)
-    }
-    logger.error = (message) => {
-      errorLogs.push(message)
-      error(message)
-    }
-    await consumeMessages()
-    // start kafka producer
-    await producer.init()
-    // start the application (kafka listener)
-    app = require('../../src/app')
-    // wait until consumer init successfully
-    while (true) {
-      if (infoLogs.some(x => String(x).includes('Kick Start'))) {
-        break
-      }
-      await sleep(config.WAIT_TIME)
-    }
-  })
-
-  after(async () => {
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    await testHelper.deleteRequest(`${config.REVIEW_API_URL}/${review.id}`, m2mToken)
-
-    res = await helper.getRequest(`${config.REVIEW_SUMMATION_API_URL}`, { submissionId }, m2mToken)
-    const [reviewSummation] = res.body
-    await testHelper.deleteRequest(`${config.REVIEW_SUMMATION_API_URL}/${reviewSummation.id}`, m2mToken)
-
-    // restore logger
-    logger.error = error
-    logger.info = info
-    logger.debug = debug
-
-    try {
-      await producer.end()
-    } catch (err) {
-      // ignore
-    }
-    try {
-      await app.end()
-    } catch (err) {
-      // ignore
-    }
-  })
-
-  beforeEach(() => {
-    // clear logs
-    infoLogs = []
-    debugLogs = []
-    errorLogs = []
-  })
-
-  it('Should setup healthcheck with check on kafka connection', async () => {
-    const healthcheckEndpoint = `http://localhost:${process.env.PORT || 3000}/health`
-    let result = await request.get(healthcheckEndpoint)
-    should.equal(result.status, 200)
-    should.deepEqual(result.body, { checksRun: 1 })
-    debugLogs.should.match(/connected=true/)
-  })
-
-  it('Should handle invalid json message', async () => {
-    const { testMessage } = testTopics.create
-    await producer.send({
-      topic: testMessage.topic,
-      message: {
-        value: '[ invalid'
-      }
-    })
-    await waitJob()
-    should.equal(errorLogs[0], 'Invalid message JSON.')
-  })
-
-  it('Should handle incorrect topic field message', async () => {
-    const { testMessage } = testTopics.create
-    let message = _.cloneDeep(testMessage)
-    message.topic = 'invalid'
-    await producer.send({
-      topic: testMessage.topic,
-      message: {
-        value: JSON.stringify(message)
-      }
-    })
-    await waitJob()
-    should.equal(errorLogs[0], 'The message topic invalid doesn\'t match the Kafka topic or.notification.create.')
-  })
-
-  it('processor create review success', async () => {
-    await sendMessage(testTopics.create.testMessage)
-    await waitJob()
-    // wait for the data updated in remote server
-    await sleep(config.WAIT_TIME)
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    should.equal(review.score, 90)
-    should.equal(review.typeId, 'c56a4180-65aa-42ec-a945-5fd21dec0503')
-  })
-
-  it('processor update review success', async () => {
-    await sendMessage(testTopics.update.testMessage)
-    await waitJob()
-    // wait for the data updated in remote server
-    await sleep(config.WAIT_TIME)
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    should.equal(review.score, 95)
-    should.equal(review.typeId, 'c56a4180-65aa-42ec-a945-5fd21dec0503')
-  })
-
-  it('test invalid parameters, userId is forbidden for create review message.', async () => {
-    let message = _.cloneDeep(testTopics.create.testMessage)
-    message.payload.userId = '12345'
-    await sendMessage(message)
-    await waitJob()
-    assertErrorMessage('"userId" is not allowed')
-  })
-
-  it('test invalid parameters, fail to retrieve review with given criteria.', async () => {
-    let message = _.cloneDeep(testTopics.update.testMessage)
-    message.payload.scorecardId = 300001611
-    await sendMessage(message)
-    await waitJob()
-    assertErrorMessage('Review doesn\'t exist under criteria')
-  })
-
-  it('test invalid eventType, fail to retrieve review with given criteria.', async () => {
-    let message = _.cloneDeep(testTopics.create.testMessage)
-    message.payload.eventType = 'INVALID_TYPE'
-    await sendMessage(message)
-    await waitJob()
-    assertErrorMessage('Invalid or not supported eventType: INVALID_TYPE')
-  })
-
-  for (const op of ['create', 'update']) {
-    let { requiredFields, integerFields, stringFields, testMessage } = testTopics[op]
-
-    it('test invalid parameters, field submissionId incorrect', async () => {
-      let message = _.cloneDeep(testMessage)
-      message.payload.submissionId = 111111111
-      await sendMessage(message)
-      await waitJob()
-      assertErrorMessage('Incorrect submission id 111111111')
-    })
-
-    it('test invalid parameters, fail to get reviewType UUID.', async () => {
-      let message = _.cloneDeep(testMessage)
-      message.payload.reviewTypeId = 12
-      await sendMessage(message)
-      await waitJob()
-      assertErrorMessage('Incorrect review type id 12')
-    })
-
-    for (const requiredField of requiredFields) {
-      if (requiredField !== 'topic') {
-        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
-          let message = _.cloneDeep(testMessage)
-          message = _.omit(message, requiredField)
-          await sendMessage(message)
-          await waitJob()
-          assertErrorMessage(`"${_.last(requiredField.split('.'))}" is required`)
-        })
-      }
-    }
-
-    for (const stringField of stringFields) {
-      if (stringField !== 'topic') {
-        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
-          let message = _.cloneDeep(testMessage)
-          _.set(message, stringField, 123)
-          await sendMessage(message)
-          await waitJob()
-          assertErrorMessage(`"${_.last(stringField.split('.'))}" must be a string`)
-        })
-      }
-    }
-
-    for (const integerField of integerFields) {
-      it(`test invalid parameters, invalid integer type field ${integerField}(wrong number)`, async () => {
-        let message = _.cloneDeep(testMessage)
-        _.set(message, integerField, 'string')
-        await sendMessage(message)
-        await waitJob()
-        assertErrorMessage(`"${_.last(integerField.split('.'))}" must be a number`)
-      })
-
-      it(`test invalid parameters, invalid integer type field ${integerField}(wrong integer)`, async () => {
-        let message = _.cloneDeep(testMessage)
-        _.set(message, integerField, 1.1)
-        await sendMessage(message)
-        await waitJob()
-        if (integerField === 'payload.reviewTypeId') {
-          assertErrorMessage(`"${_.last(integerField.split('.'))}" must be one of [1, 2, 5, 6, 7, 8, 9, 10, 11, 12]`)
-        } else {
-          assertErrorMessage(`"${_.last(integerField.split('.'))}" must be an integer`)
-        }
-      })
-    }
-  }
-})
diff --git a/test/unit/review.processor.test.js b/test/unit/review.processor.test.js
new file mode 100644
index 0000000..c49ad7d
--- /dev/null
+++ b/test/unit/review.processor.test.js
@@ -0,0 +1,166 @@
+/**
+ * Mocha tests of the Scorecard Review Processor.
+ */
+process.env.NODE_ENV = 'test'
+
+global.Promise = require('bluebird')
+
+const _ = require('lodash')
+const config = require('config')
+const ReviewProcessorService = require('../../src/services/ReviewProcessorService')
+const testHelper = require('../common/testHelper')
+const { testTopics } = require('../common/testData')
+
+describe('Topcoder - Scorecard Review Processor Unit Test', () => {
+  before(async () => {
+    testHelper.interceptLogger()
+  })
+
+  after(async () => {
+    testHelper.restoreLogger()
+  })
+
+  beforeEach(() => {
+    testHelper.clearInterceptedLogging()
+  })
+
+  it('processor create review success', async () => {
+    await ReviewProcessorService.processReview(testTopics.create.testMessage)
+
+    testHelper.assertDebugMessage('Get submission')
+    testHelper.assertDebugMessage('Submission id: b91a0ca3-3988-4899-bab4-c789f22def39')
+    testHelper.assertDebugMessage('Get review type')
+    testHelper.assertDebugMessage('Review type id: ff5742d6-22bf-4734-b632-add6641078be')
+    testHelper.assertDebugMessage('Create review')
+  })
+
+  it('processor update review success', async () => {
+    await ReviewProcessorService.processReview(testTopics.update.testMessage)
+
+    testHelper.assertDebugMessage('Get submission')
+    testHelper.assertDebugMessage('Submission id: b91a0ca3-3988-4899-bab4-c789f22def39')
+    testHelper.assertDebugMessage('Get review type')
+    testHelper.assertDebugMessage('Review type id: ff5742d6-22bf-4734-b632-add6641078be')
+    testHelper.assertDebugMessage('Get review')
+    testHelper.assertDebugMessage('Review id: 9c1c080a-b54f-46c4-b87b-6218038be765')
+    testHelper.assertDebugMessage('Update review')
+  })
+
+  it('test invalid parameters, userId is forbidden for create review message.', async () => {
+    let message = _.cloneDeep(testTopics.create.testMessage)
+    message.payload.userId = '12345'
+    try {
+      await ReviewProcessorService.processReview(message)
+      throw new Error('should not throw error here')
+    } catch (err) {
+      testHelper.assertValidationError(err, '"userId" is not allowed')
+    }
+  })
+
+  it('test invalid parameters, fail to retrieve review with given criteria.', async () => {
+    let message = _.cloneDeep(testTopics.update.testMessage)
+    message.payload.scorecardId = 300001611
+    try {
+      await ReviewProcessorService.processReview(message)
+      throw new Error('should not throw error here')
+    } catch (err) {
+      testHelper.assertErrorMessage('Review doesn\'t exist under criteria')
+    }
+  })
+
+  it('test invalid eventType, fail to retrieve review with given criteria.', async () => {
+    let message = _.cloneDeep(testTopics.create.testMessage)
+    message.payload.eventType = 'INVALID_TYPE'
+    try {
+      await ReviewProcessorService.processReview(message)
+      throw new Error('should not throw error here')
+    } catch (err) {
+      testHelper.assertErrorMessage('Invalid or not supported eventType: INVALID_TYPE')
+    }
+  })
+
+  for (const op of ['create']) {
+    let { requiredFields, integerFields, stringFields, testMessage } = testTopics[op]
+
+    it('test invalid parameters, field submissionId incorrect', async () => {
+      let message = _.cloneDeep(testMessage)
+      message.payload.submissionId = 111111111
+      try {
+        await ReviewProcessorService.processReview(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertErrorMessage('Incorrect submission id 111111111')
+      }
+    })
+
+    it('test invalid parameters, fail to get reviewType UUID.', async () => {
+      let message = _.cloneDeep(testMessage)
+      message.payload.reviewTypeId = 12
+      try {
+        await ReviewProcessorService.processReview(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertErrorMessage('Incorrect review type id 12')
+      }
+    })
+
+    for (const requiredField of requiredFields) {
+      if (requiredField !== 'topic') {
+        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
+          let message = _.cloneDeep(testMessage)
+          message = _.omit(message, requiredField)
+          try {
+            await ReviewProcessorService.processReview(message)
+            throw new Error('should not throw error here')
+          } catch (err) {
+            testHelper.assertValidationError(err, `"${_.last(requiredField.split('.'))}" is required`)
+          }
+        })
+      }
+    }
+
+    for (const stringField of stringFields) {
+      if (stringField !== 'topic') {
+        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
+          let message = _.cloneDeep(testMessage)
+          _.set(message, stringField, 123)
+          try {
+            await ReviewProcessorService.processReview(message)
+            throw new Error('should not throw error here')
+          } catch (err) {
+            testHelper.assertValidationError(err, `"${_.last(stringField.split('.'))}" must be a string`)
+          }
+        })
+      }
+    }
+
+    for (const integerField of integerFields) {
+      it(`test invalid parameters, invalid integer type field ${integerField}(wrong number)`, async () => {
+        let message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 'string')
+        try {
+          await ReviewProcessorService.processReview(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          testHelper.assertValidationError(err, `"${_.last(integerField.split('.'))}" must be a number`)
+        }
+      })
+
+      it(`test invalid parameters, invalid integer type field ${integerField}(wrong integer)`, async () => {
+        let message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 1.1)
+        try {
+          await ReviewProcessorService.processReview(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          console.log(err.message)
+          if (integerField === 'payload.reviewTypeId') {
+            testHelper.assertValidationError(err, `"${_.last(integerField.split('.'))}" must be one of [${Object.keys(config.REVIEW_TYPES).join(', ')}]`)
+          } else {
+            testHelper.assertValidationError(err, `"${_.last(integerField.split('.'))}" must be an integer`)
+          }
+        }
+      })
+    }
+  }
+})
diff --git a/test/unit/submission.processor.test.js b/test/unit/submission.processor.test.js
new file mode 100644
index 0000000..6d3170d
--- /dev/null
+++ b/test/unit/submission.processor.test.js
@@ -0,0 +1,209 @@
+/**
+ * Mocha tests of the Scorecard Submission Processor.
+ */
+process.env.NODE_ENV = 'test'
+
+global.Promise = require('bluebird')
+
+const _ = require('lodash')
+const config = require('config')
+const testHelper = require('../common/testHelper')
+const SubmissionProcessorService = require('../../src/services/SubmissionProcessorService')
+const { testTopics, avScanTopic, reviewActionTopic } = require('../common/testData')
+
+describe('Topcoder - Scorecard Submission Processor Unit Test', () => {
+  before(async () => {
+    testHelper.interceptLogger()
+  })
+
+  after(async () => {
+    testHelper.restoreLogger()
+  })
+
+  beforeEach(() => {
+    testHelper.clearInterceptedLogging()
+  })
+
+  for (const topic of [config.AGGREGATE_SUBMISSION_TOPIC]) {
+    const { operation, requiredFields, integerFields, stringFields, dateFields,
+      booleanFields, testMessage } = testTopics[topic]
+
+    it(`processor ${operation} submission success`, async () => {
+      await SubmissionProcessorService.processSubmission(testMessage)
+
+      testHelper.assertDebugMessage('Scorecard id: 30001610')
+      testHelper.assertDebugMessage('Current phase: Registration')
+      testHelper.assertDebugMessage('Post Kafka message for score system AV Scan')
+      testHelper.assertDebugMessage(`"topic": "${avScanTopic}"`)
+      testHelper.assertDebugMessage('"originator": "tc-scorecard-processor"')
+      testHelper.assertDebugMessage('"timestamp": "')
+      testHelper.assertDebugMessage('"mime-type": "application/json"')
+      testHelper.assertDebugMessage('"status": "unscanned"')
+      testHelper.assertDebugMessage(`"submissionId": "${testMessage.payload.id}"`)
+      testHelper.assertDebugMessage(`"url": "${testMessage.payload.url}"`)
+      testHelper.assertDebugMessage('"fileName": "30054740-8547899-SUBMISSION_ZIP-1554188341581.zip"')
+      testHelper.assertDebugMessage('Post Kafka message for score system OR')
+      testHelper.assertDebugMessage(`"topic": "${reviewActionTopic}"`)
+      testHelper.assertDebugMessage(`"resource": "${testMessage.payload.resource}"`)
+      testHelper.assertDebugMessage(`"id": "${testMessage.payload.id}"`)
+      testHelper.assertDebugMessage(`"type": "${testMessage.payload.type}"`)
+      testHelper.assertDebugMessage(`"url": "${testMessage.payload.url}"`)
+      testHelper.assertDebugMessage(`"memberId": ${testMessage.payload.memberId}`)
+      testHelper.assertDebugMessage(`"legacyChallengeId": ${testMessage.payload.legacyChallengeId}`)
+      testHelper.assertDebugMessage(`"created": "${testMessage.payload.created}"`)
+      testHelper.assertDebugMessage(`"updated": "${testMessage.payload.updated}"`)
+      testHelper.assertDebugMessage(`"createdBy": "${testMessage.payload.createdBy}"`)
+      testHelper.assertDebugMessage(`"updatedBy": "${testMessage.payload.updatedBy}"`)
+      testHelper.assertDebugMessage(`"submissionPhaseId": ${testMessage.payload.submissionPhaseId}`)
+      testHelper.assertDebugMessage(`"fileType": "${testMessage.payload.fileType}"`)
+      testHelper.assertDebugMessage(`"isFileSubmission": ${testMessage.payload.isFileSubmission ? 'true' : 'false'}`)
+      testHelper.assertDebugMessage(`"eventType": "${operation.toUpperCase()}"`)
+    })
+
+    it('test challenge not found.', async () => {
+      const message = _.cloneDeep(testMessage)
+      message.payload.legacyChallengeId = 89898989
+      try {
+        await SubmissionProcessorService.processSubmission(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertErrorMessage('Error: cannot GET /v4/challenges/89898989 (404)')
+      }
+    })
+
+    it('test no matched score system.', async () => {
+      const message = _.cloneDeep(testMessage)
+      message.payload.legacyChallengeId = 30054674
+      await SubmissionProcessorService.processSubmission(message)
+
+      testHelper.assertDebugMessage('Scorecard id: 30001610')
+      testHelper.assertDebugMessage('Current phase: Stalled')
+      testHelper.assertNoDebugMessage('Post Kafka message for score system')
+    })
+
+    it('test invalid parameters, resource field is invalid', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.resource', 'abc')
+      try {
+        await SubmissionProcessorService.processSubmission(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertValidationError(err, '"resource" must be one of [submission]')
+      }
+    })
+
+    it('test invalid parameters, type field is invalid', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.type', 'abc')
+      try {
+        await SubmissionProcessorService.processSubmission(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertValidationError(err, '"type" must be one of [Contest Submission]')
+      }
+    })
+
+    it('test invalid parameters, id field is invalid GUID', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.id', 'invalid-guid')
+      try {
+        await SubmissionProcessorService.processSubmission(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertValidationError(err, '"id" must be a valid GUID')
+      }
+    })
+
+    it('test invalid parameters, url field is invalid URL', async () => {
+      const message = _.cloneDeep(testMessage)
+      _.set(message, 'payload.url', 'invalid-url')
+      try {
+        await SubmissionProcessorService.processSubmission(message)
+        throw new Error('should not throw error here')
+      } catch (err) {
+        testHelper.assertValidationError(err, '"url" must be a valid uri')
+      }
+    })
+
+    for (const requiredField of requiredFields) {
+      if (requiredField !== 'topic') {
+        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
+          let message = _.cloneDeep(testMessage)
+          message = _.omit(message, requiredField)
+          try {
+            await SubmissionProcessorService.processSubmission(message)
+            throw new Error('should not throw error here')
+          } catch (err) {
+            testHelper.assertValidationError(err, `"${_.last(requiredField.split('.'))}" is required`)
+          }
+        })
+      }
+    }
+
+    for (const stringField of stringFields) {
+      if (stringField !== 'topic') {
+        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
+          const message = _.cloneDeep(testMessage)
+          _.set(message, stringField, 123)
+          try {
+            await SubmissionProcessorService.processSubmission(message)
+            throw new Error('should not throw error here')
+          } catch (err) {
+            testHelper.assertValidationError(err, `"${_.last(stringField.split('.'))}" must be a string`)
+          }
+        })
+      }
+    }
+
+    for (const dateField of dateFields) {
+      it(`test invalid parameters, invalid date type field ${dateField}`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, dateField, 'invalid-date')
+        try {
+          await SubmissionProcessorService.processSubmission(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          testHelper.assertValidationError(err,
+            `"${_.last(dateField.split('.'))}" must be a number of milliseconds or valid date string`)
+        }
+      })
+    }
+
+    for (const booleanField of booleanFields) {
+      it(`test invalid parameters, invalid boolean type field ${booleanField}`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, booleanField, 'abc')
+        try {
+          await SubmissionProcessorService.processSubmission(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          testHelper.assertValidationError(err, `"${_.last(booleanField.split('.'))}" must be a boolean`)
+        }
+      })
+    }
+
+    for (const integerField of integerFields) {
+      it(`test invalid parameters, invalid integer type field ${integerField} (wrong number)`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 'string')
+        try {
+          await SubmissionProcessorService.processSubmission(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          testHelper.assertValidationError(err, `"${_.last(integerField.split('.'))}" must be a number`)
+        }
+      })
+
+      it(`test invalid parameters, invalid integer type field ${integerField} (wrong integer)`, async () => {
+        const message = _.cloneDeep(testMessage)
+        _.set(message, integerField, 1.1)
+        try {
+          await SubmissionProcessorService.processSubmission(message)
+          throw new Error('should not throw error here')
+        } catch (err) {
+          testHelper.assertValidationError(err, `"${_.last(integerField.split('.'))}" must be an integer`)
+        }
+      })
+    }
+  }
+})
diff --git a/test/unit/test.js b/test/unit/test.js
deleted file mode 100644
index f055555..0000000
--- a/test/unit/test.js
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- * Mocha tests of the OR review Processor.
- */
-process.env.NODE_ENV = 'test'
-
-const _ = require('lodash')
-const config = require('config')
-const should = require('should')
-const helper = require('../../src/common/helper')
-const logger = require('../../src/common/logger')
-const ProcessorService = require('../../src/services/ProcessorService')
-const testHelper = require('../common/testHelper')
-const { testTopics } = require('../common/testData')
-
-describe('Topcoder - OR Review Processor Unit Test', () => {
-  let infoLogs = []
-  let errorLogs = []
-  let debugLogs = []
-  const info = logger.info
-  const error = logger.error
-  const debug = logger.debug
-  let m2mToken
-
-  /**
-   * Assert validation error
-   * @param err the error
-   * @param message the message
-   */
-  const assertValidationError = (err, message) => {
-    err.isJoi.should.be.true()
-    should.equal(err.name, 'ValidationError')
-    err.details.map(x => x.message).should.containEql(message)
-    errorLogs.should.not.be.empty()
-    errorLogs.should.containEql(err.stack)
-  }
-
-  /**
-   * Sleep with time from input
-   * @param time the time input
-   */
-  async function sleep (time) {
-    await new Promise((resolve) => {
-      setTimeout(resolve, time)
-    })
-  }
-
-  before(async () => {
-    // generate M2M token
-    m2mToken = await helper.getM2Mtoken()
-    // inject logger with log collector
-    logger.info = (message) => {
-      infoLogs.push(message)
-      info(message)
-    }
-    logger.debug = (message) => {
-      debugLogs.push(message)
-      debug(message)
-    }
-    logger.error = (message) => {
-      errorLogs.push(message)
-      error(message)
-    }
-  })
-
-  after(async () => {
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    await testHelper.deleteRequest(`${config.REVIEW_API_URL}/${review.id}`, m2mToken)
-
-    res = await helper.getRequest(`${config.REVIEW_SUMMATION_API_URL}`, { submissionId }, m2mToken)
-    const [reviewSummation] = res.body
-    await testHelper.deleteRequest(`${config.REVIEW_SUMMATION_API_URL}/${reviewSummation.id}`, m2mToken)
-
-    // restore logger
-    logger.error = error
-    logger.info = info
-    logger.debug = debug
-  })
-
-  beforeEach(() => {
-    // clear logs
-    infoLogs = []
-    debugLogs = []
-    errorLogs = []
-  })
-
-  it('processor create review success', async () => {
-    await ProcessorService.process(testTopics.create.testMessage)
-    // wait for the data updated in remote server
-    await sleep(config.WAIT_TIME)
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    should.equal(review.score, 90)
-    should.equal(review.typeId, 'c56a4180-65aa-42ec-a945-5fd21dec0503')
-  })
-
-  it('processor update review success', async () => {
-    await ProcessorService.process(testTopics.update.testMessage)
-    // wait for the data updated in remote server
-    await sleep(config.WAIT_TIME)
-    const submissionId = '5035ded4-db41-4198-9fdf-096671114317'
-    let res = await helper.getRequest(config.REVIEW_API_URL,
-      { submissionId, reviewerId: 151743, scoreCardId: 300001610 },
-      m2mToken)
-    const [review] = res.body
-    should.equal(review.score, 95)
-    should.equal(review.typeId, 'c56a4180-65aa-42ec-a945-5fd21dec0503')
-  })
-
-  it('test invalid parameters, userId is forbidden for create review message.', async () => {
-    let message = _.cloneDeep(testTopics.create.testMessage)
-    message.payload.userId = '12345'
-    try {
-      await ProcessorService.process(message)
-      throw new Error('should not throw error here')
-    } catch (err) {
-      assertValidationError(err, '"userId" is not allowed')
-    }
-  })
-
-  it('test invalid parameters, fail to retrieve review with given criteria.', async () => {
-    let message = _.cloneDeep(testTopics.update.testMessage)
-    message.payload.scorecardId = 300001611
-    try {
-      await ProcessorService.process(message)
-      throw new Error('should not throw error here')
-    } catch (err) {
-      errorLogs.should.not.be.empty()
-      errorLogs[1].should.containEql('Review doesn\'t exist under criteria')
-    }
-  })
-
-  it('test invalid eventType, fail to retrieve review with given criteria.', async () => {
-    let message = _.cloneDeep(testTopics.create.testMessage)
-    message.payload.eventType = 'INVALID_TYPE'
-    try {
-      await ProcessorService.process(message)
-      throw new Error('should not throw error here')
-    } catch (err) {
-      err.message.should.containEql('Invalid or not supported eventType: INVALID_TYPE')
-    }
-  })
-
-  for (const op of ['create', 'update']) {
-    let { requiredFields, integerFields, stringFields, testMessage } = testTopics[op]
-
-    it('test invalid parameters, field submissionId incorrect', async () => {
-      let message = _.cloneDeep(testMessage)
-      message.payload.submissionId = 111111111
-      try {
-        await ProcessorService.process(message)
-        throw new Error('should not throw error here')
-      } catch (err) {
-        errorLogs.should.not.be.empty()
-        errorLogs[1].should.containEql('Incorrect submission id 111111111')
-      }
-    })
-
-    it('test invalid parameters, fail to get reviewType UUID.', async () => {
-      let message = _.cloneDeep(testMessage)
-      message.payload.reviewTypeId = 12
-      try {
-        await ProcessorService.process(message)
-        throw new Error('should not throw error here')
-      } catch (err) {
-        errorLogs.should.not.be.empty()
-        errorLogs[1].should.containEql('Incorrect review type id 12')
-      }
-    })
-
-    for (const requiredField of requiredFields) {
-      if (requiredField !== 'topic') {
-        it(`test invalid parameters, required field ${requiredField} is missing`, async () => {
-          let message = _.cloneDeep(testMessage)
-          message = _.omit(message, requiredField)
-          try {
-            await ProcessorService.process(message)
-            throw new Error('should not throw error here')
-          } catch (err) {
-            assertValidationError(err, `"${_.last(requiredField.split('.'))}" is required`)
-          }
-        })
-      }
-    }
-
-    for (const stringField of stringFields) {
-      if (stringField !== 'topic') {
-        it(`test invalid parameters, invalid string type field ${stringField}`, async () => {
-          let message = _.cloneDeep(testMessage)
-          _.set(message, stringField, 123)
-          try {
-            await ProcessorService.process(message)
-            throw new Error('should not throw error here')
-          } catch (err) {
-            assertValidationError(err, `"${_.last(stringField.split('.'))}" must be a string`)
-          }
-        })
-      }
-    }
-
-    for (const integerField of integerFields) {
-      it(`test invalid parameters, invalid integer type field ${integerField}(wrong number)`, async () => {
-        let message = _.cloneDeep(testMessage)
-        _.set(message, integerField, 'string')
-        try {
-          await ProcessorService.process(message)
-          throw new Error('should not throw error here')
-        } catch (err) {
-          assertValidationError(err, `"${_.last(integerField.split('.'))}" must be a number`)
-        }
-      })
-
-      it(`test invalid parameters, invalid integer type field ${integerField}(wrong integer)`, async () => {
-        let message = _.cloneDeep(testMessage)
-        _.set(message, integerField, 1.1)
-        try {
-          await ProcessorService.process(message)
-          throw new Error('should not throw error here')
-        } catch (err) {
-          console.log(err.message)
-          if (integerField === 'payload.reviewTypeId') {
-            assertValidationError(err, `"${_.last(integerField.split('.'))}" must be one of [${Object.keys(config.REVIEW_TYPES).join(', ')}]`)
-          } else {
-            assertValidationError(err, `"${_.last(integerField.split('.'))}" must be an integer`)
-          }
-        }
-      })
-    }
-  }
-})