CLI for managing your Tradle MyCloud instance
- Prerequisites
- Docker
- Install and load current configuration
- Updating tradleconf
- Customize
- Deploy
- Updating MyCloud
- Destroy
- Restore
- Logging
- Common Commands
- Get web/mobile app links, deployment info, blockchain address
- Load remote models, styles and configuration
- Push bot/plugins configuration
- Set admin email for alerts
- Change database autoscaling
- Disable MyCloud
- Set days before logs transition to Amazon Glacier
- Set days before logs are deleted permanently
- Blockchain
- Alerts
- Built-in Plugins
- Terms and Conditions
- Lens
- Prefill form
- ComplyAdvantage
- OpenCorporates
- Onfido
- Centrix
- Document Checker
- TrueFace
- RankOne
- FacialRecognition
- DocumentValidity
- Customize message
- Webhooks
- Deployment
- Conditional auto-approve
- Sme onboarding
- Sme auto-approve
- Data Import / Remediation
- Required Forms
- Controlling person registration
- Controlling entity validation
- Verify Phone Number
- Prefill Beneficial Owners
- Modification History
- Inter-Form conditionals
- Troubleshooting
Note: optional if you only plan on running MyCloud in development mode on your machine.
If you don't have one yet, get one. There's a pretty generous free tier.
Note: optional if you only plan on running MyCloud in development mode on your machine.
Click here. You'll be prompted to fill out a MyCloud configuration form. When you do, you'll be given a launch link. Follow it to launch your MyCloud in AWS.
While you wait, read on.
Note: currently, the following regions are supported: US East (Virginia), Asia Pacific (Singapore), or Asia Pacific (Sydney). If you need to launch in a different region, please submit an issue on this repository. For most, we can provision support at a moment's notice.
- Install
- create a new IAM user with AdministratorAccess
- Configure your credentials:
aws configure
oraws configure --profile <profileName>
. This will set up your AWS credentials in~/.aws/
If you want to inspect logs from your lambda functions in realtime, you'll need to install awslogs, as the command tradleconf log
uses awslogs underneath.
To use tradleconf via docker, you can add the following function to your ~/.bash_profile
:
tradleconf() {
docker pull tradle/conf
docker run --rm -v $HOME/.aws:/root/.aws -v $(pwd):/app/conf tradle/conf:latest $@
}
Then use the tradleconf
command in your shell as described below
Note: the below instructions are for managing a single MyCloud instance.
- Install
tradleconf
globally:npm install -g @tradle/conf
(you may needsudo
depending on how you installed Node.js) - Create a new directory in which you will keep your configuration. In it, initialize your configuration with
tradleconf init
. This will create a file called.env
- Pull your remote configuration in with
tradleconf load --all
. Or pull in a specific part of it, e.g.:
tradleconf load --models
tradleconf load --style
tradleconf load --bot
tradleconf load --terms
Try to use the latest version of tradleconf
at all times. tradleconf
checks for updates as you use it, but at any time, you can update it yourself in the same way you installed it (see the Install section)
The following sections are optional, e.g. if you don't have Custom Models, skip the custom models section. If you don't have custom styles, skip the Custom Styles section, etc.
See sample custom models in ./models-sample
. You can create your own in ./models
and lenses in ./lenses
. Put each model in a separate json file where the file name is [yourModel.id].json. See ./models-sample/my.custom.NameForm.json and ./lenses-sample/my.custom.lens.PersonalInfo.json for examples
Define your provider's style in ./conf/style.json
(see ./conf/style.sample.json). Style must adhere to the StylesPack model.
See more details and screenshots for styles here
Set your bot's configuration in ./conf/bot.json
. See ./conf/bot.sample.json for an example. Also, see the Plugins section for how to configure the currently available plugins.
If you have Terms and Conditions you want your customers to accept prior to interacting with your bot, add them in ./conf/terms-and-conditions.md
(see ./conf/terms-and-conditions.sample.md)
You will also need to add a block in the plugins
block in conf/bot.json
to enable/disable the T's and C's. See the plugin configuration below.
Several of the services Tradle pre-integrates with need to be enabled explicitly before use, and are launched in a separate AWS cloudformation stack.
To enable/update them, run:
tradleconf enable-kyc-services
After the command completes (~20 minutes), you'll be able to configure the respective plugins
To specify which kyc services to enable, run:
tradleconf set-kyc-services --name1 --name2
(run tradleconf set-kyc-services --help
to see what's available)
To delete your kyc-services stack (it's stateless, so you can always create a new one):
tradleconf disable-kyc-services
For developers: adding a new service option can be tracked in git history for changes made at 2020-04-05 for idrnd-liveface
You can deploy your configuration to your local Tradle development environment running on your machine, or to your Tradle MyCloud running in AWS.
tradleconf deploy --local --all
Or if you only want to deploy a particular item:
- models:
tradleconf deploy --local --models
- styles:
tradleconf deploy --local --style
- bot configuration:
tradleconf deploy --local --bot
- terms and conditions:
tradleconf deploy --local --terms
Same as above, minus the --local
flag. You will be asked for confirmation unless you add the --remote
flag.
See docs/updates.md
Releases follow semver. A version like 1.9.4
represents MAJOR.MINOR.PATCH
or in other words MAJOR.FEATURE.BUGFIX
. For example:
1.1.7 -> 1.1.8
is bug fix release1.1.7 -> 1.2.0
is a feature release
In between releases, there are release candidates, which are experimental pre-releases of bugfixes or features for those who like to live on the bleeding edge.
Release candidates end with -rc.X
, e.g. 1.9.0-rc.1000
Release candidates come before the version they're a candidate for:
1.9.0 -> 1.9.0-rc.1000
1.9.1-rc.0 -> 1.9.1
1.9.1-rc.20 -> 1.9.1
A sample timeline goes like this, with releases in bold:
1.8.3 # BUGFIX RELEASE
1.9.0-rc.0 # pre-release new feature
1.9.0-rc.1 # pre-release bugfix
1.9.0-rc.2 # pre-release another bugfix
# # ...
1.9.0-rc.7 # bugs fixed, new feature stabilized, ready for release
1.9.0 # REGULAR FEATURE RELEASE
1.9.1-rc.0 # pre-release bugfix
1.9.1 # REGULAR BUGFIX RELEASE
# # ...
1.9.13
1.10.0-rc.0 # pre-release new feature
1.10.0-rc.1 # pre-release bugfix
1.10.1 # REGULAR BUGFIX RELEASE
# ...
If murder is in your heart, you can destroy your Tradle MyCloud irreversibly using tradleconf destroy
For whatever reasons, sometimes you may want to restore a failed or corrupted stack, and even restore your data to a point in time. See the Restore documentation.
tradleconf log onmessage -s 5m # log onmessage since 5m ago
tradleconf tail onmessage -s 5m # log onmessage since 5m ago, tail
tradleconf log -s 5m # log some function (you'll get a chooser prompt)
tradleconf log --help # get additional tips
tradleconf info --remote
sample response:
{
"links": {
"result": {
"mobile": "https://link.tradle.io/chat?provider=569a4dc1fc69f6137dede81ca0ff77c1a5feb0f4a7bdc73e0007f5ed3a1d1f60&host=https%3A%2F%2Ftv5n42vd5f.execute-api.us-east-1.amazonaws.com%2Fdev",
"web": "https://app.tradle.io/#/chat?provider=569a4dc1fc69f6137dede81ca0ff77c1a5feb0f4a7bdc73e0007f5ed3a1d1f60&host=https%3A%2F%2Ftv5n42vd5f.execute-api.us-east-1.amazonaws.com%2Fdev",
"employeeOnboarding": "https://app.tradle.io/#/applyForProduct?provider=569a4dc1fc69f6137dede81ca0ff77c1a5feb0f4a7bdc73e0007f5ed3a1d1f60&host=https%3A%2F%2Ftv5n42vd5f.execute-api.us-east-1.amazonaws.com%2Fdev&product=tradle.EmployeeOnboarding"
}
},
"version": {
"commit": "c403d33",
"version": "1.0.0",
"branch": "master"
},
"chainKey": {
"type": "ethereum",
"pub": "04d7ad3d714dac85ee6f91381eeb688c0d8766c274400a4ecae6a29896ee83e4221f880fc0d2bc6adc0647c043e0683daada1d2ccf7a9e3e7170400ed63b69e7fa",
"fingerprint": "fe134e1332f37b8bb8df74c0aa60c2d4b3e6e1f4",
"networkName": "rinkeby"
},
"apiBaseUrl": "https://tv5n42vd5f.execute-api.us-east-1.amazonaws.com/dev"
}
tradleconf load --remote
tradleconf deploy --remote --bot
tradleconf set-admin-email --email <email>
Command to let you change to the new on-demand autoscaling:
tradleconf set-db-autoscaling --on-demand
Note: changing to on-demand autoscaling is a strictly throttled DB configuration operation
to revert:
tradleconf set-db-autoscaling --provisioned
If for some reason or other, you need to disable your deployment temporarily, you can run:
tradleconf disable --remote
This will turn most of your cloud functions off. Mobile/web clients will be unable to reach your MyCloud.
To re-enable your deployment:
- go to the AWS lambda console
- find xxx-cli lambda
- remove DISABLED from this lambda Environment variables
- Save the changes
- Run:
tradleconf enable --remote
tradleconf set-logs-transition --days <days>
tradleconf set-logs-ttl --days <days>
To check your address and balance, you can use the balance
command, e.g.:
tradleconf balance --remote
To top up, send funds to that address. Make sure you're sending funds on the right blockchain network!
Funds are typically specified in the lowest unit of the particular blockchain, e.g. in satoshis for bitcoin, and wei for ethereum.
By default, MyCloud seals in 'single' sealing mode, meaning it seals objects individually. If you're up to MyCloud version v2.3.0
, you can change the sealing mode to 'batch'. For example, to batch objects every 10 minutes, and create one seal per batch, you would run:
tradleconf set-sealing-mode --mode batch --period-in-minutes 10
To switch back to 'single' mode:
tradleconf set-sealing-mode --mode single
After deploying MyCloud (and sometimes after a major update), you will receive an email from AWS at the admin email address you specified, asking you to confirm an SNS subscription (Amazon's Simple Notification Service). If you want your MyCloud to alert you when its balance is low, and/or about other issues, confirm that subscription.
Find below annotated examples from ./conf/bot.sample.json
Purpose: require new users to accept T's and C's before anything else
Prerequisite: deploy terms and conditions as described above
Example config:
// ...
"plugins": {
// ...
"termsAndConditions": {
"enabled": true
}
}
Purpose: request common forms with custom lenses
Example config:
// ...
"plugins": {
// ...
"lens": {
// for the nl.tradle.DigitalPassport product...
"nl.tradle.DigitalPassport": {
// when requesting form tradle.PhotoID, specify lens io.safere.lens.PhotoID
"tradle.PhotoID": "io.safere.lens.PhotoID"
}
}
}
Purpose: prefill forms sent to the user with sensible defaults
Example config:
// ...
"plugins": {
// ...
"prefillForm": {
// for the nl.tradle.DigitalPassport product...
"nl.tradle.DigitalPassport": {
// when requesting form tradle.PhotoID, prefill country to New Zealand
"tradle.PhotoID": {
"country": {
"id": "tradle.Country_NZ"
}
}
}
}
}
Purpose: upon receiving certain forms from the user, trigger checks using Comply Advantage API
Example config:
// ...
"plugins": {
// ...
"complyAdvantage": {
"credentials": {
"apiKey": "..."
},
"products": {
// for the tradle.CordaKYC product...
"tradle.CordaKYC": {
"filter": {
"fuzziness": 1,
"filter": {
"types": ["sanction"]
}
},
// Create a property map you want to use for running this check.
// Property map's values are the property in the form and keys how they named in plugin.
// Properties could be derived from different forms.
// Here is an example when data are derived from one form the tradle.BusinessInformation
// with the following ComplyAdvantage API settings:
"propertyMap": {
"tradle.BusinessInformation": {
"companyName": "companyName",
"registrationDate": "registrationDate"
}
}
}
}
}
}
Purpose: upon receiving certain forms from the user, trigger checks using OpenCorporates
Example config:
// ...
"plugins": {
// ...
"openCorporates": {
"apiKey": "...",
"products": {
"tradle.CordaKYC": [
"tradle.BusinessInformation"
]
}
}
}
Purpose: upon receiving certain forms from the user, trigger checks using Onfido
Note: currently this is available only for the products tradle.onfido.CustomerVerification and tradle.pg.CustomerOnboarding. Will be generally available soon.
Example config:
// ...
"plugins": {
// ...
"onfido": {
"apiKey": "..."
}
}
Purpose: upon receiving certain forms from the user, trigger checks using Centrix
Example config:
// ...
"plugins": {
// ...
"centrix": {
"credentials": {
"test": true, // use test server
"httpCredentials": {
"username": "...",
"password": "..."
},
"requestCredentials": {
"subscriberId": "...",
"userId": "...",
"userKey": "..."
}
},
"products": {
"nl.tradle.DigitalPassport": {}
}
}
}
Provider: DocumentChecker Purpose: Check authenticity of the Photo ID document using Keesing Document Checker.
Example config:
// ...
"plugins": {
// ...
"documentChecker": {
"account": "...",
"username": "...",
"test": true
}
}
Provider: TrueFace Purpose: detect whether a selfie is a spoof
Example config:
// ...
"plugins": {
// ...
"trueface": {
"token": "...",
"products": {
"nl.tradle.DigitalPassport": [
"tradle.Selfie"
],
"tradle.CertifiedID": [
"tradle.Selfie"
]
}
}
}
Provider: RankOne Purpose:
- compare photo id vs selfie photo for similarity
- analyze a photo with a face, extract various information such as demographics and orientation
Example config:
// ...
"plugins": {
// ...
"rankone-checks": {
// no options at the moment
}
}
Purpose: upon receiving PhotoID and Selfie forms, trigger checks using NtechLab Facial Recognition
Example config:
// ...
"plugins": {
// ...
"facial-recognition": {
"url": "http://...", // URL ntechlab server
"token": "...",
"threshold": "strict"
}
}
To test it you need to run local tunnel
lt -p 4572 -s pick-a-hostname
It will return url that you pass as a parameter to your local server
S3_PUBLIC_FACING_HOST=https://pick-a-hostname.localtunnel.me node --debug --inspect --max_old_space_size=4096 ./node_modules/.bin/sls offline start
Purpose: upon receiving PhotoID form, check the validity of expiration date, viable age, countries of nationality and issuer if applicable
Example config:
// ...
"plugins": {
// ...
"documentValidity": {
}
// ...
}
Purpose: customize the messages for various types sent to the user (e.g. form requests)
Example config:
// ...
"plugins": {
// ...
"customize-message": {
"tradle.FormRequest": {
"tradle.ProductRequest": "See our list of products",
"tradle.TermsAndConditions": "Please review our Terms and Conditions",
"tradle.PhotoID": "Please click to scan your **ID document**",
"tradle.Selfie": "Thank you. Now take a '**selfie**' photo of yourself that I can match against your ID document",
"tradle.Residence": {
"first": "Thank you. Now I need you to provide your **residence** information",
"nth": "Thank you. Do you have another **residence**? If yes, tap Add, otherwise tap Next"
},
"tradle.ApplicationSubmitted": {
"tradle.nl.DigitalPassport": "You're all done! We'll get back to you shortly"
}
}
}
}
Purpose: subscribe to events, handle them outside MyCloud
Example config:
// ...
"plugins": {
// ...
"webhooks": {
// optional. If provided, webhook requests will carry an hmac of the body
// in the x-webhook-auth header (see ./examples/webhook-handler.js)
"hmacSecret": "[a private random string]",
// subscriptions to events you want to receive
"subscriptions": [
// ... get notified about all inbound messages
{
"topic": "msg:i",
"endpoint": "https://example.com/tradle/webhook1"
},
// ... get notified about inbound messages of a particular type
{
"topic": "msg:i:tradle.PhotoID",
"endpoint": "https://example.com/tradle/webhook2"
},
// ... get notified when a resource is saved
{
"topic": "save",
"endpoint": "https://example.com/tradle/webhook3"
},
// ... get notified when a particular type of resource is saved
{
"topic": "save:tradle.Application",
"hmacSecret": "use a different hmacSecret per subscriptin if you want",
"endpoint": "https://example.com/tradle/webhook4"
}
]
}
}
See an example webhook processor in ./examples/webhooks. To run it:
cd examples/webhooks
npm install
npm start
Purpose: required to support the tradle.cloud.Deployment
product. This product allows others to deploy MyCloud children based on your own MyCloud
Example config:
// ...
"plugins": {
// ...
"deployment": {
"senderEmail": "[an email address you control]",
"replication": {
"regions": [
// regions you want to support
"us-east-1",
"ap-southeast-2"
]
}
}
}
Purpose: allow to auto approve customer application if all the listed checks passed
...
"plugins": {
// ...
"conditional-auto-approve": {
"products": {
"tradle.CertifiedID": [
// List of checks that need to 'Pass' in order to auto-approve the application
"tradle.SanctionsCheck",
"tradle.DocumentValidityCheck",
...
],
"tradle.CorporateBankAccount": [
"tradle.CorporationExistsCheck",
"tradle.SanctionsCheck",
...
]
}
}
}
Purpose: allow to prefill subsidiary application from associated resource created when main application was submitted
...
"plugins": {
// ...
"sme-onboarding": {}
}
Purpose: allow to auto approve SME application if all child applications (subsidiaries, controlling persons) were approved
...
"plugins": {
// ...
"sme-auto-approve": [
{
"child": "tradle.legal.ControllingPersonOnboarding",
"parent": "tradle.legal.LegalEntity"
},
...
]
}
If you already have data from a customer and don't want them to re-enter it, you can have them import it in their Tradle app by scanning a QR code. To create the data bundle and claim stub, see ./docs/data-import.md
Purpose: customize a product's required forms
Example config:
// ...
"plugins": {
// ...
"required-forms": {
"tradle.EmployeeOnboarding": [
"tradle.PhotoID"
]
}
}
Purpose: When SME administrator fills out CP and CE for officers and beneficial owners (BO) of the company, the notification should be sent out for the corresponding officer and/or BO to get onboarded
...
"plugins": {
// ...
"controllingPersonRegistration": {
"senderEmail": "...",
"products": {
"io.lenka.LegalEntity": [
"tradle.legal.LegalEntityControllingPerson"
],
...
}
}
}
Purpose: When SME administrator fills out CP and CE for officers and beneficial owners (BO) of the company, the notification should be sent out for the corresponding officer and/or BO to get onboarded
...
"plugins": {
// ...
"controllingEntityValidation": {
"senderEmail": "...",
"products": {
"io.lenka.LegalEntity": [
"tradle.legal.LegalEntityControllingPerson"
],
...
}
}
}
Purpose: verify a user controls a phone number
Example config:
// ...
"plugins": {
// ...
"verify-phone-number": {
"products": {
"tradle.CurrentAccount": {
"tradle.PersonalInfo": {
"property": "phones"
}
}
}
}
}
Purpose: Reduce/eliminate data entry for corporate onboarding. Information for prefill is taken from the passed Check resources that confirm company existence and list BO
Example config:
...
"plugins": {
// ...
"prefill-controllingPerson": {
[product ID]: {
"skipBo": {
[form ID]: {
"regulated": true,
"country": ["GB", "DE"]
}
}
}
}
}
Purpose: Records the data and source of data prefilled from the third party sources and records all the changes made by client. Additionally creates a Check resource in case there was a prefill with 3rd party data and it differs from the changes the client applied to it.
Example config:
...
"plugins": {
// ...
"client-edits": {
"distance": 5
}
}
Purpose: change flow of the application based on the settings in previously submitted forms.
Example config to request the form 'tradle.ProofOfAddress' only if the property 'country' in the previously submitted form 'tradle.Residence' is set to US
...
"plugins": {
// ...
"tradle.Product": [
"tradle.Residence",
...
{
"tradle.ProofOfAddress": "add: forms['tradle.Residence'].country = 'US'"
}
],
}
Symptom: InvalidInput: expected "adminEmail"
Cause: in MyCloud <= 2.3.0, you need to confirm the AWS SNS Subscription for Alerts. Look for an email with subject "AWS Notification - Subscription Confirmation" and confirm it. If the confirmation expired, go to the AWS SNS Console for your AWS region (e.g. https://console.aws.amazon.com/sns/v2/home?region=us-east-1#/topics), find the topic that looks like [your-stack-name]-alerts-alarm
(e.g. tdl-tradle-ltd-dev-alerts-alarm
), and create and confirm an Email subscription to that topic.
This command creates an additional CloudFormation stack. Should it fail when you run it, find the failed stack in the AWS CloudFormation console, and ask the Tradle team to help you interpret the error.
In general, this stack is stateless (doesn't store any data), so it's safe to delete and re-create.