GithubHelp home page GithubHelp logo

test-at-home's Introduction

Test At Home

Project Status โš ๏ธ ๐Ÿšจ

The USPS web store was successfully launched on January 18, 2022.

This back-up solution is no longer being actively developed nor used in production. It is targeted to be archived at the end of February 2022.

Overview

A web-based, mobile-responsive solution for the public to submit a pre-order request for 1 set of four COVID-19 tests to be sent directly to their home through the USPS infrastructure. This solution is intended to be a back-up for the USPS web store, if it cannot stand peak traffic.

The launch date for this solution is January 17, 2022.

For more detail, see the product scope doc

Operations

Development

If you're new to Rails, see the Getting Started with Rails guide for an introduction to the framework.

Local Setup

  • Install Ruby 3.0.3
  • Install NodeJS 16.13.1
  • Install PostgreSQL: brew install postgresql
    • Add postgres to your PATH if it wasn't done automatically echo 'export PATH="/usr/local/opt/postgresql/bin:$PATH"' >> ~/.zshrc
    • Start the server brew services start postgresql
  • Install Ruby dependencies: bundle install
  • Install chromedriver for integration tests: brew install --cask chromedriver
    • Chromedriver must be allowed to run. You can either do that by:
      • The command line: xattr -d com.apple.quarantine $(which chromedriver) (this is the only option if you are on Big Sur)
      • Manually: clicking "allow" when you run the integration tests for the first time and a dialogue opens up
  • Install JS dependencies: yarn install
  • Build CSS and JS: yarn build && yarn build:css
  • Create database: bundle exec rake db:create
  • Run migrations: bundle exec rake db:migrate
  • Run the server: ./bin/dev
  • Visit the site: http://localhost:3000

For performance, we cache the root page using the Cache-Control header. By default, the form should be cached for:

env max cache age
dev/test/ci 10 seconds
stage-small 1 minute
stage 10 minutes
prod 1 hour

Local Configuration

Environment variables can be set in development using the dotenv gem.

Consistent but sensitive credentials should be added to config/credentials.yml.env by using $ rails credentials:edit

Any changes to variables in .env that should not be checked into git should be set in .env.local.

If you wish to override a config globally for the test Rails environment you can set it in .env.test.local. However, any config that should be set on other machines should either go into .env or be explicitly set as part of the test.

Authentication

This application does not contain an authentication component. All interaction is public/guest

Inline <script> and <style> security

The system's Content-Security-Policy header prevents <script> and <style> tags from working without further configuration. Use <%= javascript_tag nonce: true %> for inline javascript.

See the CSP compliant script tag helpers ADR for more information on setting these up successfully.

Managing translation files

We use the gem i18n-tasks to manage translation files. Here are a few common tasks:

Add missing keys across locales:

$ i18n-tasks add-missing

Key sorting:

$ i18n-tasks normalize

Removing unused keys:

$ i18n-tasks unused
$ i18n-tasks remove-unused

For more information on usage and helpful rake tasks to manage translation files, see the documentation.

Testing

Running tests

  • Tests: bundle exec rake spec
  • Ruby linter: bundle exec rake standard
  • Accessibility scan: ./bin/pa11y-scan
  • Dynamic security scan: ./bin/owasp-scan
  • Ruby static security scan: bundle exec rake brakeman
  • Ruby dependency checks: bundle exec rake bundler:audit
  • JS dependency checks: bundle exec rake yarn:audit

Run everything: bundle exec rake

CI/CD

CircleCI is in use as our CI/CD pipeline. All scans run on each PR, and security scans are also run on a daily basis.

Deployment

Each environment has dependencies on a PostgreSQL RDS instance managed by cloud.gov. See cloud.gov docs for information on RDS.

Foundry configuration

Last updated Jan 17 at 2:30p EST

Our application is deployed across four foundries, all different than the usual cloud.gov. They have been stood up for this application, anticipating high load.

Each foundry has:

  • one org: gsa-tts-test-kits
  • two spaces: staging and prod

In each foundatation's prod space, there are two deployed application configurations: one with Smarty Streets API enabled and one with it disabled. We are launching with Smarty Streets enabled, and plan to route traffic to the applications where it is disabled in case of a Smarty service problem.

Foundry 1: CF_FOUNDRY_API: api.fr.wb.cloud.gov

Foundry 2 CF_FOUNDRY_API: api.fr.wc.cloud.gov

Foundry 3 CF_FOUNDRY_API: api.fr.ea.cloud.gov

Foundry 4 CF_FOUNDRY_API: api.fr.eb.cloud.gov

Questions? Ask in #tts-covidtest-devops for platform, and #tts-covidtest-rails for application development and config.

Staging

First time only: create DB service with cf create-service aws-rds micro-psql test_at_home-rds-stage

cf push --strategy rolling --vars-file config/deployment/stage.yml --var rails_master_key=$(cat config/master.key)

Production

First time only: create DB service with cf create-service aws-rds <<SERVICE_PLAN_NAME>> test_at_home-rds-prod

cf push --strategy rolling --vars-file config/deployment/prod.yml --var prod_rails_master_key=$(cat config/credentials/production.key)

Configuring ENV variables in cloud.gov

All configuration that needs to be added to the deployed application's ENV should be added to the env: block in manifest.yml

Items that are both public and consistent across staging and production can be set directly there.

Otherwise, they are set as a ((variable)) within manifest.yml and the variable is defined depending on sensitivity:

Credentials and other Secrets

  1. Store variables that must be secret using CircleCI Environment Variables
  2. TKTK, this step needs to be updated for CircleCI deployment pipeline. Add the secret to the env: block of the deploy action as in this example
  3. TKTK, this step needs to be updated for CircleCI deployment pipeline. Add the appropriate --var addition to the push_arguments line on the deploy action as in this example

Non-secrets

Configuration that changes from staging to production, but is public, should be added to config/deployment/stage.yml and config/deployment/prod.yml

Documentation

Architectural Decision Records (ADR) are stored in doc/adr To create a new ADR, first install ADR-tools if you don't already have it installed.

  • brew install adr-tools

Then create the ADR:

  • adr new Title Of Architectural Decision

This will create a new, numbered ADR in the doc/adr directory.

Contributing

This will continue to evolve as the project moves forward.

  • Pull down the most recent main before checking out a branch
  • Write your code
  • If a big architectural decision was made, add an ADR
  • Submit a PR
    • If you added functionality, please add tests.
    • All tests must pass!
  • Ping the other engineers for a review.
  • At least one approving review is required for merge.
  • Rebase against main before merge to ensure your code is up-to-date!
  • Merge after review.
    • Squash commits into meaningful chunks of work and ensure that your commit messages convey meaning.

Story Acceptance

TBD

test-at-home's People

Contributors

dependabot[bot] avatar hartsick avatar hursey013 avatar mitchellhenke avatar mogul avatar natalie-gov avatar rahearn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

test-at-home's Issues

State dropdown not showing selected state

Steps to reproduce:

  1. Visit homepage
  2. Fill in all required information, but leave first name blank. Click submit
  3. See that the state select does not have a persisted value when page re-rendered with errors

What if we have to go live without data delivery implemented?

Thus far it our team has not been able to get in touch with USPS. @jacky chang has asked our team to think through contingencies on how to handle the situation where we are going to be taking in orders but have not touched data delivery.

Brainstorming:

Being able to contact the user after order submission

  • Add content to let users know there's a possibility they will have to resubmit
  • Add explicit content that without an email, user may need to resubmit their package
  • Support outgoing emails to users
  • โ›” Are we able to make outbound phone calls?

Persist data as entered by user

  • Unsure if this was already plan of record, but save info as entered by user; not just corrected address from validation API

Stakeholder awareness

  • Ensure stakeholders across GSA/TTS & USDS/OMB are aware of risk

Explore usage of Smarty Streets API for address validation

Explore address validation
With Smarty Streets API
To discover how we might deliver the best address validation experience

Resources

Approach

  • Prototype server-side validations of address
    • How do we know if address is allowable
    • Assigning and displaying errors to model
  • Prototype client-side validations of address
    • Displaying to client when address has been changed
  • Prototype client-side autocomplete
  • Benchmark / measure API usage of autocomplete
  • Test cases referenced in questions below
  • Write up notes

Note: this is now only using the US street address validation API, since autocomplete has been deprioritized for launch.

Questions to answer

  • Can we restrict validations to USPS data?
    • Yes, by enabling strict match mode or by enabling invalid or enhanced APIs but filtering any dpv_match_codes that are not Y, S, or D. Match output strategies invalid or enhanced are the only ways to suggest addresses to the user (strict will not`).
  • Can we validate addresses in US territories?
    • Yes, though presenting the full address returned from the API is slightly different than how we do this with other addresses (optional urbanization field). Context: we have tested this with a few addresses from Puerto Rico.
  • Can we validate addresses in overseas military bases?
  • What settings do we need to use to make it as close to the USPS online API as possible?

Running notes

  • In the Ruby SDK example on address validation, there's a note that the 'urbanization' field is only used for addresses in Puerto Rico. What does this mean for us?
  • Does state need a specific format (eg state two-letter code)? What does it need for territories and overseas?
  • We can use match output strategy strict to only return results if they have dpv_match_code of Y, S, or D, which we think maps to USPS deliverability. However, this seems to be very strict in practice - and won't return suggestions
  • When addresses meet the dpv_match_code, they can also return dpv_footnotes with information from USPS about the address. See api docs. I assume this is only present for S and D types but not sure. Additionally, Smarty adds a footnotes section (docs].
  • I'm having a problem matching US military bases. I'm using examples based on the USPS documentation and can't get the API to return a result because they're fake. Do we have real ones we can test with? Same for territories (using addresses from Google Maps)
  • USPS site doesn't seem to accept dpv_match_code of D, and only accepts Y and S.
  • When dpv_match_code is S additional information is preserved in the returned address even though it is incorrect.
  • Suggestion from Mapbox on autocomplete: start sending keystrokes after ~6 characters

Finalize product spec

Finalize product spec:

  • Document
  • Sequence chart

Acceptance:

  • Document and sequence chart baselined and checked into this repo.

Consent text

Finalize consent text with GSA and USPS.
Need to know what USPS will do with the information we send them.
Especially will it be used for anything outside of order fulfillment (ex. will it be used to strengthen USPS address verification API?)

sanity test (staging-covidtest.usa.gov) - Browsers & Devices

Windows

  • Tablet
  • Desktop - Internet Explorer ๐ŸŸข
  • Desktop - MS Edge ๐ŸŸข

MacOS

  • Safari ๐ŸŸข
  • Chrome ๐ŸŸข
  • Firefox ๐ŸŸข

iOS

  • iPhone latest
  • iPhone 6 Safari ๐ŸŸข
  • iPad Safari ๐ŸŸข

Android

  • Native Android (Pixel)
  • Samsung device
  • Chrome
  • Kindle Fire Silk ๐ŸŸข

Add client-side validations

We'd like client-side validations that match server-side validations so we don't have to hit the server for person to know they need to correct their entry.

Strategy discussion on resiliency of validation API

Decision from 1/11 team discussion

Must have by 1/18 launch (captured in #67)

  • Create a parallel app that will intake orders
    • Email is mandatory for this app
  • Orders will be saved without validating address
  • Upon API recovery, a background process will validate address for those orders
  • Email can be used to contact users of any post processing issues encountered by that process

Nice to have by 1/18 launch captured in #68

  • Parallel app would implement, on top of above, an address validation against USPS API

Background

Given:

  • We cannot assume we can contact the user after they have submitted an order
  • We have to confirm deliverability to prevent package loss

Then:

  • We cannot save an order to our data store (i.e. give user confirmation of an order) until the address has been confirmed deliverable (see #43 on criteria of deliverability).
  • We should understand what our stance is for if the primary validation API suffers an outage

Thoughts:

  • Implement a backup mechanism based on either the (online USPS API, offline USPS address DB, other unpaid system that uses canonical USPS address information and can support #57.
  • Have graceful fallback to the backup mechanism
  • If backup fails, then error out the order
  • If persistent failure of primary and backup, throw alarm to on call team and stop taking orders.

As someone seeking a test, I need to enter my information so the federal government knows where to send my test kit.

This is the happy path as described in the intial prototype (https://gsa.invisionapp.com/console/share/UR3ACI81CG)

Acceptance criteria

  • Front end has implemented all pages in initial prototype.
  • English only.
  • Orders saved into data store.
  • Use placeholder text for Privacy/Consent language.
  • Email is optional (though users are informed that without email, they will not receive any status updates).

Decide on throttling strategies

We've discussed using a captcha of some sort on the front-end.

Issues:

  • is there a captcha that is accessible?
  • is the captcha verifiable on the backend? If we use a fully-cached front-end then we can't use the CSRF token to filter out submissions that bypass the frontend entirely. How can we filter out scripted curl submissions, for example?

As someone who does not have access to email, I am able to complete an order

Email adoption in the United States is in the mid/low 90s with lower numbers amongst:

  • Elderly
  • Minorities/Persons of Color

While the USPS fulfillment system requires an email, we will investigate being able to support order intake with an email address.

Acceptance Criteria

  • Order flow will make email optional
  • User is informed *prior to order submission that if email is not entered, they will not receive any status updates from USPS
  • Email will be populated with [email protected] (or some other email address).
    • Note: another story will be entered if there are specific email uniqueness constraints on emails sent to USPS)

Validation - Address

** Background**

USPS guest checkout looks at entered addresses to confirm that it has found the address within its database.

  • It automatically modifies the address to match what is closest match to its records.
    Ex. 1312 West Roscoe Street becomes 1312 W ROSCOE ST
  • It rejects addresses it cannot match.

This is different from most patterns other e-commerce sites use. They often give the user a choice between a suggested updated address and what the user entered.

If it is confirmed that USPS fulfillment system requires addresses that match a deliverable address (DPVConfirmation), then we have to:

Acceptance Criteria

  • If the address is changed, on "Review" page, user has clear indicator that their address was changed to what is in the system.
    • Implementation detail, this means addresses that received DPVConfirmation values of Y,S
  • The user can choose to go back.
  • If address is not found, an error is shown on the "Order entry" page.
    • This is for both errors where no match was found and a non deliverable error was received DPVConfirmation values of D,N
  • If address validation cannot be completed
    • If transient failure, hard error and user can retry
    • If API completely offline, system should stop taking orders. This is undesirable, so redundancy/fallback of validation API is needed.
  • Implementation detail: At minimum we will store the following fields (includes both user visible fields as well as non user visible fields):
<Address1>
<Address2>
<City>
<CityAbbreviation>
<State>
<Zip5>
<Zip4>
<DeliveryPoint>
<CarrierRoute>
<DPVConfirmation>

Migrate CI pipeline

Move CI pipeline to circleci because this repo has a limit of 0 minutes available for Github Actions

CircleC Free Plan:

Private repositories will have 2,500 credits/week available, which replenish every Sunday 12:00 UTC

  • Add CircleCI as check against repository
  • Pull over checks from Github Actions:
    • Static analysis
    • Dependency scans (Ruby and Yarn)
    • OWASP (potentially not, since Log4j vuln) owasp/zap2docker-weekly has an updated log4j
    • Pa11y
    • Rspec
  • Update README add information about CircleCI

Multiple app configs for probable scenarios

Rather than redeploy or restage in case of launch-day issues, we can and maybe should have multiple instances of the app running with different configs for likely runbook plays. We could then swap configs with cf map-route very quickly.

two scenarios that come to mind:

  • dropping captcha
  • using alternate storage backend (e.g. s3, other databases?)

MVP address validation resiliency

From #60, where a decision on address validation resiliency was made

In the event that SmartyStreets encounters an outage:

  • Create a parallel app that will intake orders
    • Backend: email is mandatory
    • Frontend: email is mandatory
    • Frontend address presence validation, no API validation
    • Backend address presence validation, no API validation
    • Remove "email is optional" text
    • Deploy to staging env
  • Orders will be saved without validating address
  • Upon API recovery, a background process will validate address for those orders
  • Email can be used to contact users of any post processing issues encountered by that process
  • Sitchover/Trigger mechanism from the primary app to this parallel app when SmartyStreets outage occurs

Validation - Email fields

Email validation controls

  • Error messages - at minimum meets WCAG 2.1 standards level AA.
  • (To confirm with USPS) Check MX record of domain name

Explore using Recaptcha for bot prevention

Ryan's sample code:

    def recaptcha_valid?(user_response)
      return true unless recaptcha_required?
      return false if user_response.blank?
      uri = URI("https://www.google.com/recaptcha/api/siteverify")
      response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
        request = Net::HTTP::Post.new uri
        request.set_form_data secret: Rails.application.credentials.recaptcha[:site_secret], response: user_response
        http.request request
      end
      json = JSON.parse response.body
      json["success"]
    end

Recaptcha docs: https://cloud.google.com/recaptcha-enterprise/docs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.