Git Product home page Git Product logo

customers's Introduction

moov-io/customers

Project Status

Moov Customers has been deprecated in favor of a more direct service for uploading ACH files. We’ve also realized that KYC/KYB, data modeling, workflows, and risk analysis are difficult to open-source. We are interested in hearing how you have solved these problems internally and want to develop something in the open. Thank you to everyone who has contributed and helped us grow.


GoDoc Build Status Coverage Status Go Report Card Apache 2 licensed

This project focuses on verifying the identity of people who are legally able to hold and transfer currency in the United States. It provides services related to:

The goal of this project is to provide objective, detailed due diligence on individuals and companies in the financial sector — in a modernized and extensible way.

If you believe you have identified a security vulnerability please responsibly report the issue as via email to [email protected]. Please do not post it to a public issue tracker.

FFIEC Bank Secrecy Act - Customer Identification Program

Docs: docs | API Endpoints | Admin API Endpoints

Getting Started

Customers has a Docker Compose setup which you can run locally. This uses the latest releases of Customers and Watchman.

$ docker-compose up
Creating customers_watchman_1 ... done
Creating customers_customers_1 ... done
...
customers_1  | ts=2020-03-06T22:56:24.2184402Z caller=main.go:50 startup="Starting moov-io/customers server version v0.4.0-rc1"
customers_1  | ts=2020-03-06T22:56:24.393462Z caller=watchman.go:102 watchman="using http://watchman:8084 for Watchman address"
customers_1  | ts=2020-03-06T22:56:24.3951132Z caller=main.go:171 startup="binding to :8087 for HTTP server"

Once the systems start you can access Customers via http://localhost:8087 and Watchman's web interface or api:

  1. API Endpoints
  2. Admin Endpoints

Read through the project docs over here to get an understanding of the purpose of this project and how to run it.

Getting Help

channel info
Documentation Project documentation for our community.
GitHub Issues Public tracker of issues with our community. Please open a GitHub Issue if you're able to reproduce problems or to request features.
Twitter @moov You can follow Moov's Twitter feed to get updates on our projects. You can also tweet us to ask questions or share comments.
Slack #moov-io Join the slack channel to discuss with other contributors about the development of Moov's open source projects.

Contributing

Yes please! Please review our Contributing guide and Code of Conduct to get started! Checkout our issues for first time contributors for something to help out with.

Test Coverage

Improving test coverage is a good candidate for new contributors while also allowing the project to move more quickly by reducing regressions issues that might not be caught before a release is pushed out to our users. One great way to improve coverage is by adding edge cases and different inputs to functions.

License

Apache License 2.0 See LICENSE for details.

customers's People

Contributors

adamdecaf avatar alovak avatar atonks2 avatar bkmoovio avatar darwinz avatar nlakritz avatar renovate-bot avatar vxio avatar wadearnold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

customers's Issues

accounts: KYC/OFAC check on Holder Name

In #122 we added HolderName to an Account. This is a legal name of the account. Typically this varies from the Customer name in business Customers - the holder name would be an individual and Customer name is their business.

We need to verify the holder name passes an OFAC check.

meta: rename project

What were you trying to do?
Customers (this repository/service) gets confused with Customer (model) and multiple Customer objects (Customers) a bit too much. We need a better way to refer to this service vs the Customer model.

What did you expect to see?
A clear name for this service.

Options

  • filecabinet: Storage and organization of PII - Customer, Account, legal entity, etc
  • rolodex: [rolling] device used to store business contact information

Add DB persistence to data models

Currently, all data is stored in SQLLite in memory. Customers and the event log should be configured to be stored in a restart persistent data stores such as MySQL or Postgres.

Identity Verification of Customers

There are several levels of identity verification of customers, they are (in order, case insensitive):

  • deceased
  • rejected
  • none
  • reviewrequired (Review Required)
  • kyc
  • ofac
  • cip

When we implement these it should be done with a type that can be compared (i.e. integers) so that KYC < CIP and we can use comparisons like customer.IdentityVerification < KYC in our codebase.

Notes: #9

docs: graphic of network calls

We should design a graphic or two for Customer's network calls. This will help quickly explain what's involved when running Customers.

documents: add option for each customer to acknowledge

Documents that a vendor or FI distribute may need to be acknowledged by each customer before money can be moved. Sometimes these documents are updated and require a re-ack.

We need to support this in Customers and have it presented in the same endpoint paygate (and others) use to read the current status/situation for a Customer.

Original notes from meeting with Wade

Had a meeting with @wadearnold on this project.

"Customer" meeting with Wade
- KYC is required before OFAC
- CIP: Customer Identification Program (for Banks and Fiancial Service companies)
- KYC (3 pieces) vs CIP (4 pieces w/ SSN)
- If we hold deposits for a customer then we need their SSN
- Validate legal name, address,

Originators need KYC and OFAC
Receivers need OFAC checks (think about allowing KYC on them too)

Allow arbitrary map of ID's (salesforceId, etc) to centralize lookups and foreign key relationships

KYC / CIP are 'affirmative' (reasonably sure) whereas OFAC is a negative match (rejection)

Identity Verification of Customer
- Rejected (level 0)
- ReviewRequired (level 1)
- None (level 2)
- OFAC Only (Run check on data I give) (level 3)
- KYC: (3 pieces of info, with workflow that verifies each) (level 4)
  - legal name, address, and date of birth
- CIP: (4 pieces, with SSN) (level 5)
  - pull credit check with SSN (verify DoB, address, etc)
  - required to hold deposits
  - require drivers license

Auth (in Customer model) might not be restricted to one Customer
 - think teller or internal employee

Profile photos (driver license) are hidden to avoid discrimination.

Documents: DriversLicense (Legal name) and Utility Bill (Address)

Prevent duplicate connected accounts per customer?

Today I can input the same routing number, account number and type combination for a customer. Should our service allow this? Would erroring expose too much information about a customer and account within Moov? (presumably you could get the full account number with the same authorization)

My worry of duplicate accounts is then needing to build functionality to merge the accounts together to make reporting on transaction history meaningful.

Can't mount sqlite file in docker container

You can't mount the sqlite file customers.db from within a docker container, as it outputs to the root directory. It should probably output to "/data/" just like Paygate.

Support Know Your Customer (KYC)

KYC (wikipedia consists of collecting legal name, address, and date of birth from a customer and validating them to "sufficiently affirm" the existence of the customer and their ability to transfer funds.

KYC is required in order to process transactions for a human in the US and typically uses a Drivers license to validate.

Notes: #9

MX Tests need troubleshooting with regards to api keys and tests failing

Customers Version: ``

What were you trying to do?
Trying to run tests in cmd/server/accounts/validator/mx/strategy_test.go

What did you expect to see?
Test passed

What did you see?
Test failed due to api creds issued by MX

How can we reproduce the problem?
Run the test cmd/server/accounts/validator/mx/strategy_test.go:TestStrategy

cmd/server: support serving over https

What were you trying to do?
We need to support running Customer's HTTP servers with TLS for all communications. This is required for production installs and needs to be documented in our guides.

After templating we need to confirm this is documented.

Protect Customer status update endpoint behind stricter auth

#5 has talked about needing more restrictive authz around some endpoints in the Customers app. Wade mentions

"We should probably limit the OAuth security scope for this action and the action should be logged. I see a "backend" application for approving these in the future."

We should look at using an existing solution like https://github.com/ory/oathkeeper or https://github.com/ory/hydra (not exactly sure the difference) instead of our home grown auth solution to limit these with users and groups.

cmd/server: support TLS in HTTP server

We need to support TLS in our HTTP server. This protects requests from inspection along the various network paths and routing. It's also required as part of several guidelines and audit requirements.

build: convert project to templater

What were you trying to do?
We need to convert Customers over to our templater which is used for all projects. This will help setup authn/z and a unified routing setup as our other apps have.

What did you expect to see?
A unified setup across all of our applications.

Add an arbitrary map of ID's (foreign keys) on Customer

We need to allow and store an arbitrary map of ID's (salesforceId, etc) to centralize lookups and foreign key relationships. This helps integrate external services with this project by offering one location to store all relationships with a customer.

Notes: #9

Store encrypted social security numbers (SSN)

We need to store social security numbers (SSN) and they can only be stored encrypted. The Go CDK has support for "Secrets" which supports the main cloud provider systems or vault. We should support GCP, AWS, and Vault as a start.

This will be used with CIP status transitions (a valid SSN is required).

Instant account verification with Plaid, MX

1. Initiate account verification

POST /customers/{customerID}/accounts/{accountID}/validate

Request:

{
  "strategy": "instant"
}

Response:

{
  "link_token":"link-sandbox-32771002-45e1-4f9b-93fd-f12442f8aa44",
  "expiration":"2020-08-25T13:07:19Z"
}

2. Use Plaid Link to obtain public_token

User should add Plaid Link integration depending on their paltform. Here is example for web:

<html>
	<body>
		<button id="link-button">Verify Account with Plaid</button>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
		<script src="https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
		<script type="text/javascript">
			var handler;

			// get link_token for Plaid Link
			$.post('/verify', {}, function(data){
				handler = Plaid.create({
					token: data.link_token,
					onSuccess: function(public_token) {
						console.log("public token", public_token);
						// send public_token to api to verify account
						$.ajax({
							type: "PUT",
							url: "/verify",
							data: {
								public_token: public_token,
							},
							success: function(data) {
								console.log("Verification result: ", data);
								// it should return account with status: verified
							},
						});
					},
				});
			});

			$('#link-button').on('click', function(e) {
				handler.open();
			});
		</script>
	</body>
</html>

Screen Shot 2020-08-24 at 16 45 17

3. Complete account verification

PUT /customers/{customerID}/accounts/{accountID}/validate

Request:

{
  "strategy": "instant",
  "public_token": "public-sandbox-59eb4718-93d8-41a0-a338-9d731d83e549"
}

Response:

{
  "accountID": "e1b1544a",
  "maskedAccountNumber": "0001027028",
  "routingNumber": "051504597",
  "status": "validated", // verified?
  "type": "checking"
}

Questions.

  1. Can we change validation API? Right now it's a PUT request and it would be helpful to split it into two separate POST and PUT.
  2. Can micro-deposits validation expire/fail and then to be re-run? Is it an issue at all? With "instant" validation we can initiate and obtain new tokens and verify account multiple times, but with micro-deposits we can't.
  3. How user will decide what kind of validation to use (micro deposits or instant)?
  4. Should we change from validate to verify?

customers: endpoint to refresh OFAC search results

Receivers (in paygate) need to be periodically updated, so Customers should support refreshing the OFAC results for a given Customer object. Callers can use it in dashboards or on a schedule depending on their business logic.

List customers with sorting and filtering

Related to #99

For customer management, it'd be useful to extend the functionality of the GET /customers endpoint.

Consider having GET /customers return a paginated list of results. My immediate need is for the sort order to be by date created.

For any paginated response, it's useful to know when you've hit the end of the series by either having the total count in the response or a marker on the response to signal the end.

We could do this in all sorts of ways, but typical REST might be something like

GET /customers?orderBy=createdAt&orderDirection=desc&limitTo=50

Also related, filtering the list of customers by status and createdAt (before or after), would be a solid start.

watchman: files are downloaded in tests

When launching the test containers of Watchman all data files are downloaded. This causes problems if the files fail to download (e.g. periodic downtime).

Should watchman's docker image include data files from the time it was built? Watchman would still download them on the interval, but have an initial set.

Account status PUT returns 200 with no body

This is a nit pick, but when updating the status of an account directly from the status endpoint, the response is a 200 but it does not include a body. A 204 would be preferred so frontend client code doesn't try to response.json() an empty response OR include a body in the response.

Verification required for transfers

In the larger Moov cluster of services ACH Transfers need to have certain verification levels on Originators and Receivers. This status needs to be exposed as part of the Customer model so paygate (and others) can compare and reject unidentified Customers.

  • Originators need KYC and OFAC
  • Receivers need OFAC checks (but can also require KYC optionally)

Notes: #9

documents: encrypt uploaded files

Customers Version: v0.5.0-dev

What were you trying to do?
When uploading a document that file is not encrypted. These files can contain PII and should be encrypted at rest.

What did you expect to see?
Data should be protected and encrypted at rest.

customers: search endpoint

We need to support searching all Customer records stored in the database. This allows the UI and other programs to find records. Creating transfers can occur well after the initial creation and UI's / services will need to relocate the correct customerID to use.

Initially I'm thinking of the following endpoint with a bunch of query params.
GET /customers

  • ?name=<string> (optional) used and split across first/last names, returns fuzzy results
  • ?email=<string> (optional) exact match (with .'s removed)
  • ?type=<string> (optional) individual and business filter

Thoughts @InfernoJJ and @joshsadler ?

customers: store beneficiary information

As part of a Customer's related data needs to be beneficiary information. This would be a name and contact point (email, phone) which can be used in the event of a Customers death.

Address verification via external API

Verifying addresses exist will come up as a feature to add into Customers. We would do this with several external API's as various customers will have existing deals with vendors and want to use them.

Edit: Lots of these services will support bulk API's, so would it be acceptable for Customers to check addresses in an async fashion? Does Customers need to re-check the address on some interval?

all: separate models by "namespace"

We need to keep models isolated and have previously done this with X-User-ID. This is often confused a bit with "users" in terms of auth or something, but instead we're going to namespace on X-Namespace. The updated naming removes an unintended connection with an auth stack.

Check OFAC on customers after creation and store results

When we create a customer let's check OFAC and store that result for use later (when we try and Verify a customer to OFAC or higher). It doesn't need to be part of the HTTP endpoint and if it fails the later status will require a new lookup.

TestGetCustomersWithVerifiedStatus flakey test

Customers Version: master

What were you trying to do?
TestGetCustomersWithVerifiedStatus on master right now is a flakey test. It seems to fail without the mainline code changing.

https://github.com/moov-io/customers/pull/139/checks?check_run_id=1109215732 was failing because of this test

It seems the similar tests added at the same time can be flakey.

What did you expect to see?
Tests should only fail when the code is broken, not for flakey reasons.

How can we reproduce the problem?

$ go test ./cmd/server/ -count 100 -run TestGetCustomersWithVerifiedStatus -v 

--- FAIL: TestGetCustomersWithVerifiedStatus (0.03s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x78 pc=0x4b0528d]

goroutine 55 [running]:
testing.tRunner.func1.1(0x4d78760, 0x5752bb0)
	/usr/local/Cellar/go/1.15/libexec/src/testing/testing.go:1057 +0x30d
testing.tRunner.func1(0xc0000d6a80)
	/usr/local/Cellar/go/1.15/libexec/src/testing/testing.go:1060 +0x41a
panic(0x4d78760, 0x5752bb0)
	/usr/local/Cellar/go/1.15/libexec/src/runtime/panic.go:969 +0x175
github.com/moov-io/customers/cmd/server.TestGetCustomersWithVerifiedStatus(0xc0000d6a80)
	/Users/adam/code/src/github.com/moov-io/customers/cmd/server/customer_search_test.go:200 +0x3ad
testing.tRunner(0xc0000d6a80, 0x4f4eef0)
	/usr/local/Cellar/go/1.15/libexec/src/testing/testing.go:1108 +0xef
created by testing.(*T).Run
	/usr/local/Cellar/go/1.15/libexec/src/testing/testing.go:1159 +0x386
FAIL	github.com/moov-io/customers/cmd/server	0.127s
FAIL

What are the GDPR implications for Customers?

I was wondering what implications the data stored in Customers has with GDPR. It's my understanding that if even one EU citizen uses our product we're supposed to comply with all of their regulations, which is pretty complicated to do. Any personal information is subject to deletion requests and must be only minimally collected.

type customerRequest struct {
	FirstName  string            `json:"firstName"`
	MiddleName string            `json:"middleName"`
	LastName   string            `json:"lastName"`
	NickName   string            `json:"nickName"`
	Suffix     string            `json:"suffix"`
	BirthDate  time.Time         `json:"birthDate"`
	Email      string            `json:"email"`
	SSN        string            `json:"SSN"`
	Phones     []phone           `json:"phones"`
	Addresses  []address         `json:"addresses"`
	Metadata   map[string]string `json:"metadata"`
}

cc @wadearnold thoughts?

Support uploading Documents for Identity Verification

We need to support uploading and parsing documents (e.g. barcodes) to help verify a customer's identity. This typically includes Drivers Licenses (for legal name) and a utility bill (for addresses).

There will be generic blob storage on the backend for each document (with encryption, ideally on immutable storage).

Notes: #9

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.